I'm a bit new to programing a windows store app.So the question is how can I save an instance of a class in to an xml or binary file.I tried some code but it isn't working.
Hope that some one can steer me in the right direction .
You can serialize your instance by using this code
/// <summary>
/// Deserializes the XML.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml">The XML.</param>
/// <returns>The instance</returns>
public static T DeserializeXml<T>(this String xml)
{
var bytes = Encoding.UTF8.GetBytes(xml);
using (var stream = new MemoryStream(bytes))
{
var serializer = new DataContractSerializer(typeof(T));
return (T)serializer.ReadObject(stream);
}
}
/// <summary>
/// Serializes the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
/// <returns>Xml</returns>
public static String SerializeXml(this Object instance)
{
using (var stream = new MemoryStream())
{
var serializer = new DataContractSerializer(instance.GetType());
serializer.WriteObject(stream, instance);
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
var result = "<?xml version='1.0' encoding='UTF-8' ?>";
result += reader.ReadToEnd();
return result;
}
}
}
Next step is to save the serialized instance text to a file.
var filename = "instance.txt";
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
var content = yourInstance.SerializeXml();
await FileIO.WriteTextAsync(file, content, Windows.Storage.Streams.UnicodeEncoding.Utf8);
Now there should be a file in your AppPackage-Local-Folder called instance.txt which contains the current instance serialized to xml.
You can use Windows.Storage to store any file, the usage is like IO operation. MSDN
IsolatedStorage is similar to this for Windows Phone apps.
Related
Few days ago our applications (iOS, Android and Windows) stopped getting the list of Pages from Microsoft OneNote via OneNote API request https://www.onenote.com/api/v1.0/me/notes/pages. Request returns HTTP OK and empty content.
Source code Windows UWP appliaction C#-XAML (from Microsoft OneNote API example https://github.com/OneNoteDev/OneNoteAPISampleWinUniversal)
public static string GET_PAGES_REQEST = APIENDPOINT + "sections/{0}/pages";
public const string APIENDPOINT = "https://www.onenote.com/api/v1.0/me/notes/";
public const string AUTHMETHOD = "Bearer";
public const string APPJSON = "application/json";
/// <summary>
/// Get meta data for ALL pages under a given section
/// </summary>
/// <param name="sectionId">Id of the section for which the page are returned</param>
/// <param name="token">Authentication token</param>
/// <param name="isEncryptedOnly">View encrypted only notes</param>
/// <remarks> The sectionId can be fetched by querying the user's sections (e.g. GET https://www.onenote.com/api/v1.0/sections ).
/// NOTE: Using this approach, you can still query pages with ALL the different params shown in examples above.
/// </remarks>
/// <returns>The converted HTTP response message</returns>
public static async Task<List<PageApiResponse>> GetListAsync(string sectionId, string token, bool isEncryptedOnly)
{
var client = new HttpClient();
// Note: API only supports JSON response.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Common.APPJSON));
//client.DefaultRequestHeaders.Add("FavorDataRecency", "true");
// Not adding the Authentication header would produce an unauthorized call and the API will return a 401
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue
(
Common.AUTHMETHOD, token
);
// Prepare an HTTP GET request to the Pages endpoint
var getMessage = new HttpRequestMessage
(
HttpMethod.Get,
isEncryptedOnly ?
String.Format(Common.GET_PAGES_ENCRYPTED_REQEST, sectionId) :
String.Format(Common.GET_PAGES_REQEST, sectionId)
);
HttpResponseMessage response = await client.SendAsync(getMessage);
string body = await response.Content.ReadAsStringAsync();
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(Errors.TranslateError(response));
var content = JObject.Parse(body);
return JsonConvert.DeserializeObject<List<PageApiResponse>>(content["value"].ToString());
}
sectionId and token is correct. isEncryptedOnly = false;
Notebooks and Sections work fine. Anybody can help me?
Controller that worked in ASP.NET Core 2.0:
[Produces("application/json")]
[Route("api/[controller]")]
[ApiController]
public class GraficResourcesApiController : ControllerBase
{
private readonly ApplicationDbContext _context;
public GraficResourcesApiController(ApplicationDbContext context)
{
_context = context;
}
[HttpGet]
public JsonResult GetGrafic(int ResourceId)
{
var sheduling = new List<Sheduling>();
var events = from e in _context.Grafic.Where(c=>c.ResourceId == ResourceId)
select new
{
id = e.Id,
title = e.Personals.Name,
start = e.DateStart,
end = e.DateStop,
color = e.Personals.Color,
personalId = e.PersonalId,
description = e.ClientName
};
var rows = events.ToArray();
return Json(rows);
}
}
in ASP.NET Core 2.1
return Json (rows);
writes that Json does not exist in the current context. If we remove Json leaving simply
return rows;
then writes that it was not possible to explicitly convert the type List () to JsonResult
How to convert to Json now?
In asp.net-core-2.1 ControllerBase does not have a Json(Object) method. However Controller does.
So either refactor the current controller to be derived from Controller
public class GraficResourcesApiController : Controller {
//...
}
to have access to the Controller.Json Method or you can initialize a new JsonResult yourself in the action
return new JsonResult(rows);
which is basically what the method does internally in Controller
/// <summary>
/// Creates a <see cref="JsonResult"/> object that serializes the specified <paramref name="data"/> object
/// to JSON.
/// </summary>
/// <param name="data">The object to serialize.</param>
/// <returns>The created <see cref="JsonResult"/> that serializes the specified <paramref name="data"/>
/// to JSON format for the response.</returns>
[NonAction]
public virtual JsonResult Json(object data)
{
return new JsonResult(data);
}
/// <summary>
/// Creates a <see cref="JsonResult"/> object that serializes the specified <paramref name="data"/> object
/// to JSON.
/// </summary>
/// <param name="data">The object to serialize.</param>
/// <param name="serializerSettings">The <see cref="JsonSerializerSettings"/> to be used by
/// the formatter.</param>
/// <returns>The created <see cref="JsonResult"/> that serializes the specified <paramref name="data"/>
/// as JSON format for the response.</returns>
/// <remarks>Callers should cache an instance of <see cref="JsonSerializerSettings"/> to avoid
/// recreating cached data with each call.</remarks>
[NonAction]
public virtual JsonResult Json(object data, JsonSerializerSettings serializerSettings)
{
if (serializerSettings == null)
{
throw new ArgumentNullException(nameof(serializerSettings));
}
return new JsonResult(data, serializerSettings);
}
Source
I am using Serilog HTTP sink for logging to Logstash in my .Net Core Project. In startup.cs I have following code to enable serilog.
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Http("http://mylogstashhost.com:5000").Enrich.WithProperty("user", "xxx").Enrich.WithProperty("serviceName", "yyy")
.MinimumLevel.Warning()
.CreateLogger();
And this code sends logs to the given http address. I can see on fiddler that following json is being posted to the logstash and logstash returns "ok" message.
{"events":[{"Timestamp":"2018-10-19T18:16:27.6561159+01:00","Level":"Warning","MessageTemplate":"abc","RenderedMessage":"abc","user":"xxx","serviceName":"yyy","Properties":{"ActionId":"b313b8ed-0baf-4d75-a6e2-f0dbcb941f67","ActionName":"MyProject.Controllers.HomeController.Index","RequestId":"0HLHLQMV1EBCJ:00000003","RequestPath":"/"}}]}
But when I checked on Kibana, I can not see this log. I tried to figure out what causes it and i realized that if I send the json as following format I can see the Log.
{"Timestamp":"2018-10-19T18:16:27.6561159+01:00","Level":"Warning","MessageTemplate":"abc","RenderedMessage":"abc","user":"xxx","serviceName":"yyy","Properties":{"ActionId":"b313b8ed-0baf-4d75-a6e2-f0dbcb941f67","ActionName":"MyProject.Controllers.HomeController.Index" ,"RequestId":"0HLHLQMV1EBCJ:00000003","RequestPath":"/"}}
So Logstash doesnt like the event to be in Events{} and also it wants "user" and "ServiceName" tags out of "Properties". Is there a way to format my Json like this?
Ok after some research and help, basically to achieve custom formats, one should implement interfaces like ITextFormatter, BatchFormatter etc.
I could achieve the format i need, by modifying ArrayBatchFormatter a little:
public class MyFormat : BatchFormatter
{
/// <summary>
/// Initializes a new instance of the <see cref="ArrayBatchFormatter"/> class.
/// </summary>
/// <param name="eventBodyLimitBytes">
/// The maximum size, in bytes, that the JSON representation of an event may take before it
/// is dropped rather than being sent to the server. Specify null for no limit. Default
/// value is 256 KB.
/// </param>
public MyFormat(long? eventBodyLimitBytes = 256 * 1024): base(eventBodyLimitBytes)
{
}
/// <summary>
/// Format the log events into a payload.
/// </summary>
/// <param name="logEvents">
/// The events to format.
/// </param>
/// <param name="output">
/// The payload to send over the network.
/// </param>
public override void Format(IEnumerable<string> logEvents, TextWriter output)
{
if (logEvents == null) throw new ArgumentNullException(nameof(logEvents));
if (output == null) throw new ArgumentNullException(nameof(output));
// Abort if sequence of log events is empty
if (!logEvents.Any())
{
return;
}
output.Write("[");
var delimStart = string.Empty;
foreach (var logEvent in logEvents)
{
if (string.IsNullOrWhiteSpace(logEvent))
{
continue;
}
int index = logEvent.IndexOf("{");
string adjustedString = "{\"user\":\"xxx\",\"serviceName\" : \"yyy\"," + logEvent.Substring(1);
if (CheckEventBodySize(adjustedString))
{
output.Write(delimStart);
output.Write(adjustedString);
delimStart = ",";
}
}
output.Write("]");
}
}
I would like to extend #nooaa answer with this variation. Instead of manipulating the string to add new objects, I would suggest using Newtonsoft.Json.Linq. This way you can append, add or remove existing properties of the object itself.
Also, instead of doing output.write after each event, you can combine all the output from the events and do output.write once at the end (a bit of performance)
public override void Format(IEnumerable<string> logEvents, TextWriter output)
{
if (logEvents == null) throw new ArgumentNullException(nameof(logEvents));
if (output == null) throw new ArgumentNullException(nameof(output));
// Abort if sequence of log events is empty
if (!logEvents.Any())
{
return;
}
List<object> updatedEvents = new List<object>();
foreach (string logEvent in logEvents)
{
if (string.IsNullOrWhiteSpace(logEvent))
{
continue;
}
// Parse the log event
var obj = JObject.Parse(logEvent);
// Add New entries
obj["#source_host"] = obj["fields"]["MachineName"].Value<string>().ToLower();
// Remove any entries you are not interested in
((JObject)obj["fields"]).Remove("MachineName");
// Default tags for any log that goes out of your app.
obj["#tags"] = new JArray() { "appName", "api" };
// Additional tags from end points (custom based on routes)
if (obj["fields"]["tags"] != null)
{
((JArray)obj["#tags"]).Merge((JArray)obj["fields"]["tags"]);
((JObject)obj["fields"]).Remove("tags");
}
updatedEvents.Add(obj);
}
output.Write(JsonConvert.SerializeObject(updatedEvents));
}
Update
Release Notes v8.0.0
With latest release, you dont override the method anymore.
namespace Serilog.Sinks.Http.BatchFormatters {
public class MyCustomFormatter: IBatchFormatter {
public void Format(IEnumerable<string> logEvents, TextWriter output) {
...
}
}
}
you don't provide any Contructors for it either.
Add queueLimitBytes along with batchFormatter and textFormatter
WriteTo.Http(new Uri(),
batchFormatter: new MyCustomFormatter(),
queueLimitBytes: 50 * ByteSize.MB,
textFormatter: new ElasticsearchJsonFormatter());
In Javascript its basically:
pubnub.publish({
channel: 'Chatbox',
message: {
username: 'username',
text: message
}
});
pubnub.subscribe({
channel: 'Chatbox',
message: handleMessage
});
function handleMessage(message) {
var messageEl = $("<li class='message'>"
+ "<span class='username'>" + message.username + ": </span>"
+ message.text
+ "</li>");
messageList.append(messageEl);
messageList.listview('refresh');
In Unity instead of using message.username. Unity gives a dictionary. Unity seems to be the more complicated one so I would like to translate the unity from string url to publish sdk, if possible.
Here is the UNity Wrapper
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PubNubWrapper : MonoBehaviour
{
public static PubNubWrapper instance;
public string PublishKey = "";
public string SubscribeKey = "";
private Dictionary<string, System.Action<string>> channelMessageHandlers = new Dictionary<string, System.Action<string>>();
private string timeToken = "o";
void Awake()
{
instance = this;
// Debug.Log("Received message: ");
}
//send the ported message
/// <summary>
/// The Publish function creates a new JSON string by creating a WWW object. The WWW object is the object
/// making the requests to the PubNub Server. Part of the Publish, Subscribe and Unsubscribe requests for web services
/// </summary>
/// <param name="message"></param>
/// <param name="channel"></param>
public void Publish(string message, string channel)
{
//esc the message so we can put it into webservices
string escapedMessage = WWW.EscapeURL(message).Replace("+", "%20"); // UNity's URL escaping function replaces spaces '+'
//form the URL
//http://pubsub/pubnub.com
// /publish
// /[publishKey]
// /[subscribe key]
// /[o
// /[channel name]
// /o
// /[JSON message data]
string url =
"http://pubsub.pubnub.com" +"/publish" +"/" + PublishKey +"/" + SubscribeKey +"/o" +"/" + channel +"/o" +"/\"" + escapedMessage + "\"";
//make the request with a newly created WWW object
WWW www = new WWW(url);
}
/// <summary>
/// Subscribe creates an open port to listen to published messages sent with a JSON string
/// </summary>
/// <param name="channel"> N/a </param>
/// <param name="messageHandler"> N/a </param>
public void Subscribe(string channel, System.Action<string> messageHandler)
{
channelMessageHandlers.Add(channel, messageHandler);
StartCoroutine(doSubscribe(channel));
}
/// <summary>
/// The doSubscribe is the action for the channel to listen to for published messages
/// </summary>
/// <param name="channel"></param>
/// <returns></returns>
IEnumerator doSubscribe(string channel)
{
//The mssage handler here will again be JSON for parsing
while (channelMessageHandlers.ContainsKey(channel))
{
// form the URL
// /http://pubsub.pubnub.com
// /subscribe
// /[subscribe key here]
// / [channel key here]
// /o
// /[time token here]
string url =
"http://pubsub.pubnub.com" +
"/subscribe" +
"/" + SubscribeKey +
"/" + channel +
"/o" +
"/" + timeToken;
// make the request
WWW www = new WWW(url);
//in Unity we can yield
// a WWW object whic makes Unity "pause"
// a subroutine until the request has either encountered and error or done
yield return www;
//www.error is a string
// it will either be null/empty if there is no error, or it
// will contain the error message if there was one
if (!string.IsNullOrEmpty(www.error))
{
//log the error to the console
Debug.LogWarning("Subscribe failed: " + www.error);
//unsibscribe from the channel automatically
// yield break causes Unity to stop exiting this
// coroutine. It is equivalent to a return function
yield break;
}
//parse the JSON response from the client from subscription
string newToken;
string[] newMessages = PubNubUtils.ParseSubscribeResponse(
www.text, out newToken);
timeToken = newToken;
//make sure there is a still a subscription
if (channelMessageHandlers.ContainsKey(channel))
{
// handle each message separately
for (int i = 0; i < newMessages.Length; i++)
{
channelMessageHandlers[channel](newMessages[i]);
}
}
}
}
/// <summary>
/// Listen to the channel for subscriptions
/// </summary>
/// <param name="channel"></param>
public void Unsubscribe(string channel)
{
channelMessageHandlers.Remove(channel);
}
}
Unity GUI components
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Chatbox : MonoBehaviour {
private string PlayerName;
private string _playerName;
private string chatText = "";
private List<string> messages = new List<string>();
private Vector2 scrollPosition = Vector2.zero;
/// <summary>
/// Initialize all the player preferences with Guestname<0-999> and the name can be changed by /OnGui
/// </summary>
void Start()
{
PlayerName = PlayerPrefs.GetString("PlayerName", "Guest" + Random.Range(0, 9999));
_playerName = PlayerName;
//subscribe to the specific room
PubNubWrapper.instance.Subscribe("Chatbox", HandleMessage);
}
/// <summary>
/// Handle message sends a string to the list of messages and deletes if over 100
/// </summary>
/// <param name="message"></param>
void HandleMessage(string message)
{
Debug.Log(message);
messages.Add(message);
if (messages.Count > 100)
messages.RemoveAt(0);
//Unity cmlamps the scroll value. Setting it sufficiently high will cause it to scroll to the bottom
scrollPosition.y = messages.Count * 100f;
}
/// <summary>
/// GUI references for changing the player's name
/// </summary>
void OnGUI()
{
_playerName = GUILayout.TextField(_playerName, GUILayout.Width(200f));
if (GUILayout.Button( "Change Name", GUILayout.Width( 200f ) ) )
{
//inform other players that the player has changed name
PubNubWrapper.instance.Publish(PlayerName + " changed their name to " + _playerName, "Chatbox");
//assign the new name
PlayerName = _playerName;
}
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Width(Screen.width), GUILayout.Height(Screen.height - 75f));
{
// display each message
for (int i = 0; i < messages.Count; i++)
{
GUILayout.Label(messages[i]);
}
}
GUILayout.EndScrollView();
GUILayout.BeginHorizontal(GUILayout.Width(Screen.width));
{
chatText = GUILayout.TextField(chatText, GUILayout.ExpandWidth(true));
if(GUILayout.Button( "Send", GUILayout.Width(100f ) ))
{
//publish the message the player types as:
// [playername] : [message]
if (chatText.StartsWith("/me "))
{
chatText = chatText.Replace("/me", "");
PubNubWrapper.instance.Publish(PlayerName + chatText, "Chatbox");
}
else
{
PubNubWrapper.instance.Publish(PlayerName + ": " + chatText, "Chatbox");
}
// clear the textbox
chatText = "";
}
}
GUILayout.EndHorizontal();
}
/// <summary>
/// Quit the chat box when the player leaves the room and save it for them later
/// </summary>
void OnApplicationQuit()
{
PlayerPrefs.SetString("PlayerName", PlayerName);
}
// Update is called once per frame
void Update () {
}
}
The other thing about this is the webpage will understand the connection, except it won't get the publish and subscribe right. I would like to eventually do more projects so it seems the biggest bottleneck is Unity but I understand I can't do much to change the Asset.
'
I do not own the rights to the code, they are taken from the PubNub website and Unity Multiplayer Games textbook. I simply just made the connection of using a runnable server.
PASSWORD() according to MySQL documentation is a double SHA1 algorithm.
In Win32 I was using this method:
public string GenerateMySQLHash(string key)
{
byte[] keyArray = Encoding.UTF8.GetBytes(key);
SHA1Managed enc = new SHA1Managed();
byte[] encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray));
StringBuilder myBuilder = new StringBuilder(encodedKey.Length);
foreach (byte b in encodedKey)
myBuilder.Append(b.ToString("X2"));
return "*" + myBuilder.ToString();
}
SHA1Managed object is not available in the Metro .net framework because the security stuff is now in Windows.Security.Cryptography and not in System.Security.Cryptography.
In the documentation, I see this example to obtain the SHA1 from a string:
public String HashMsg(String strMsg)
{
// Convert the message string to binary data.
IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
// Create a HashAlgorithmProvider object.
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1);
// Hash the message.
IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg);
// Verify that the hash length equals the length specified for the algorithm.
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
// Convert the hash to a string (for display).
return CryptographicBuffer.EncodeToBase64String(buffHash);
}
But I need a double SHA1 algorithm. Any way to do this easy as in win32?
I finally found the solution :), I hope it help you:
/// <summary>
/// Reverse a string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ReverseString(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
/// <summary>
/// MySQL PASSWORD encryption
/// </summary>
/// <param name="strMsg"></param>
/// <returns></returns>
public String HashMsg(String strMsg)
{
// Convert the message string to binary data.
IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
// Create a HashAlgorithmProvider object.
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1);
// Hash the message.
IBuffer buffHash = objAlgProv.HashData(objAlgProv.HashData(buffUtf8Msg));
// Verify that the hash length equals the length specified for the algorithm.
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
byte[] arrByteNew;
CryptographicBuffer.CopyToByteArray(buffHash, out arrByteNew);
StringBuilder myBuilder = new StringBuilder(arrByteNew.Length);
foreach (var b in arrByteNew)
myBuilder.Append(b.ToString("X2"));
// Concat with the STRING REVERSED
String stringReversed = "*" + myBuilder.ToString() + ReverseString(strMsg);
buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(s3, BinaryStringEncoding.Utf8);
buffHash = objAlgProv.HashData(objAlgProv.HashData(buffUtf8Msg));
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
CryptographicBuffer.CopyToByteArray(buffHash, out arrByteNew);
myBuilder = new StringBuilder(arrByteNew.Length);
foreach (var b in arrByteNew)
{
myBuilder.Append(b.ToString("X2"));
}
stringReversed = "*" + myBuilder.ToString();
return stringReversed;
}