Rest transfer non serializable objects - c#

Is there a way to send a non serializable object via Rest ?
I have a request class where some properies can be serialized, but not all.
The class inherits a other class from a SDK (see below 'IWorkflowContext'). This class is protected and can not be serialized - but needs to be transfered. I tried to use JSON, where the non serialization of the SDK object is an issue, when I try to serialize it binary I get a serializer exception
"Request for the permission of type
'System.Security.Permissions.SecurityPermission, mscorlib,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
failed."
My request & serialization looks like this for binary :
byte[] bytes;
IFormatter formatter = new BinaryFormatter();
using (MemoryStream s = new MemoryStream())
{
formatter.Serialize(s, userRequest);
bytes = s.ToArray();
}
stream.Write(bytes, 0, bytes.Length);
And here the Json Serialization
DataContractJsonSerializer ser = new DataContractJsonSerializer(userRequest.GetType());
ser.WriteObject(stream, userRequest);
Or another Json serializers (results in the same non serialization problem)
string json = JsonConvert.SerializeObject(userRequest);
byte[] buffer = Encoding.UTF8.GetBytes(json);
stream.Write(bytes, 0, bytes.Length);
For reference is here my class (modified for binary serialization - for Json I had for each property a Datamember flag.
[Serializable()]
public class AzureRequest
{
public string _orgaName = string.Empty;
public string _connectionString = string.Empty;
public IWorkflowContext _contextWorkflow = null;
public string _webhookOperation = string.Empty;
/// <summary>
/// The Connectionrequest describes a schema to connect to a CRM.
/// e.g. "Url=http://OrgName.crm.dynamics.com/OrgName;AuthType=Office365;Username=UserName#OrgName.onmicrosoft.com;Password=Password";
/// </summary>
public string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
}
}
/// <summary>
/// The Organization Name of the CRM to contact
/// </summary>
public string OrgaName
{
get
{
return _orgaName;
}
set
{
_orgaName = value;
}
}
/// <summary>
/// Is the running Context for the Worklfow instance
/// </summary>
public IWorkflowContext ContextWorkflow
{
get
{
return _contextWorkflow;
}
set
{
_contextWorkflow = value;
}
}
/// <summary>
/// The Operation, the Webhook should perform
/// </summary>
public string WebhookOperation
{
get
{
return _webhookOperation;
}
set
{
_webhookOperation = value;
}
}
}

Related

How to write strings and bool to a text file (comma separated)

I am trying to make a winform application. The app has 2 textboxes (firstName, lastName), a numericUpDown, and a checkbox. The app is able to read from a text file, with comma separated rows (Daniel,Brown,26,true). The app put this info in a listbox. Then you can add a new user. When you are finished adding users you press save and the new info from lisbox will be saved in that text file. I've created the read file script and add user succesfully. However I can't create the save user button so that it'll save: Daniel,Brown,26,true. I was able to save as: Daniel,Brown,26,happy.
Here is the Person Class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public bool IsHappy { get; set; }
public override string ToString()
{
var statusText = IsHappy ? "happy" : "not happy";
return $"{FirstName} {LastName} is {Age} and is {statusText}";
}
}
Here is the form.cs with it's script:
public partial class ChallengeForm : Form
{
private BindingList<Person> _persons = new BindingList<Person>();
private PersonsService _personsService;
public ChallengeForm()
{
_personsService = new PersonsService();
InitializeComponent();
WireUpDropDown();
}
private void WireUpDropDown()
{
_persons = new BindingList<Person>(_personsService.GetPersons(#"C:\Users\user\Desktop\Document.TXT"));
usersListBox.DataSource = _persons;
}
private void addUserButton_Click(object sender, EventArgs e)
{
var person = new Person { FirstName = firstNameText.Text, LastName = lastNameText.Text, Age = agePicker.Text, IsHappy = isHappyCheckbox.Checked };
_persons.Add(person);
}
private void saveListButton_Click(object sender, EventArgs e)
{
}
}
My question is how can I convert the status back to bool. And write the listbox to the text file as csv. I would be very thankfull if you could use SoC.
Here is what I've tried:
const string sPath = (#"C:\Users\user\Desktop\Document.TXT");
System.IO.StreamWriter SaveFile = new System.IO.StreamWriter(sPath);
SaveFile.Write(myperson);
foreach (var item in usersListBox.Items)
{
List<string> unwantedWords = new List<string> { "is", "and" };
var linesSplitted = item.ToString().Split(' ').ToList();
var wordsWithoutUnwantedWords = linesSplitted.Where(i => !unwantedWords.Contains(i)).ToList();
for (int i = 0; i<wordsWithoutUnwantedWords.Count; i++)
{
var isLastWord = i == wordsWithoutUnwantedWords.Count - 1;
SaveFile.Write(wordsWithoutUnwantedWords[i]);
if (!isLastWord)
{
SaveFile.Write(",");
}
Look into XML Serialization. You can just pass in your filepath and the object and the rest will be done for you by the Serialisation classes. Code below:
This is taken from DeadlyDog's awesome answer: https://stackoverflow.com/a/22417240/1623971
/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
var serializer = new XmlSerializer(typeof(T));
reader = new StreamReader(filePath);
return (T)serializer.Deserialize(reader);
}
finally
{
if (reader != null)
reader.Close();
}
}
Sample use case:
WriteToXmlFile<Person>("C:\someClass.txt", objectToSerialize);
// Read the file contents back into a variable.
Person deserializedObject = ReadFromXmlFile<Person>("C:\someClass.txt");

Json Geocode address parsing in C#

I want to get address of the location
Iam using google geocode to get address by passing lat and long.
static readonly string RequestUrl = "http://maps.google.com/maps/api/geocode/json?";
/// <summary>
/// Gets the raw object.
/// </summary>
/// <returns></returns>
protected JsonGeoData GetJsonObject() {
StringBuilder url = new StringBuilder( GeoRequest.RequestUrl);
if (this.Location != null) {
url.AppendFormat("latlng={0}", this.Location.ToString());
}
else {
url.AppendFormat("address={0}", HttpUtility.UrlEncode(this.Address));
}
url.AppendFormat("&sensor={0}", this.IsSensor.ToString().ToLower());
if (!string.IsNullOrEmpty(this.Language))
url.AppendFormat("&language={0}", HttpUtility.UrlEncode(this.Language));
if(!string.IsNullOrEmpty(this.Region))
url.AppendFormat("&region={0}", HttpUtility.UrlEncode(this.Region));
WebRequest request = WebRequest.Create(url.ToString());
using (WebResponse response = request.GetResponse()) {
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Deserialize<JsonGeoData>(reader.ReadToEnd());
}
}
}
/// <summary>
/// Gets the response.
/// </summary>
/// <returns></returns>
public GeoResponse GetResponse() {
return new GeoResponse(this.GetJsonObject());
}
/// <summary cref="A">
/// fetching location from web
/// </summary>
/// <typeparam name="T"></typeparam>
private string getloc(double plat, double plng)
{
try
{
GeoRequest objreq = new GeoRequest(plat, plng);
GeoResponse objres = objreq.GetResponse();
if (objres.Results.Count > 0)
{ return objres.Results[0].FormattedAddress; }
else
{ return "Unknown"; }
}
catch (FormatException) { return "Unknown"; }
catch (Exception)
{ return "Unknown"; }
}
iam trying to get json data from geocode and parse using serializer,
But iam getting error 'sublocality_level_2 is not a valid value for GeoAddressType.'

Why XML has empty spaces instead data inside after serialization?

After serialization sometimes xml files is filled with empty spaces. Why is it happen?
My serialization code is:
XmlSerializer serializer = new XmlSerializer(typeof(SerializableStorage));
using (StreamWriter sw = new StreamWriter(storageName, false, myEncoding))
{
serializer.Serialize(sw, messages);
}
This code serializes me messages into XML.
SerializableStorage looks like:
[XmlRoot("Storage")]
public class SerializableStorage
{
/// <summary>
/// Gets or sets an array of server messages
/// </summary>
[XmlArray("Messages")]
[XmlArrayItem("Message")]
public List<NMessage> Messages
{
get;
protected set;
}
/// <summary>
/// Public constructor
/// </summary>
public SerializableStorage()
{
Messages = new List<NMessage>();
}
}
NMessage class has all fields as public.
And deserialization if needed:
XmlSerializer serializer = new XmlSerializer(typeof(SerializableStorage));
StreamReader reader = new StreamReader(storageName, myEncoding);
StoreMessages = (SerializableStorage)serializer.Deserialize(reader);
reader.Close();
I've attached an "empty xml" example here

write list of objects to a file

I've got a class salesman in the following format:
class salesman
{
public string name, address, email;
public int sales;
}
I've got another class where the user inputs name, address, email and sales.
This input is then added to a list
List<salesman> salesmanList = new List<salesman>();
After the user has input as many salesman to the list as they like, they have the option to save the list to a file of their choice (which I can limit to .xml or .txt(which ever is more appropriate)).
How would I add this list to the file?
Also this file needs to be re-read back into a list if the user wishes to later view the records.
Something like this would work. this uses a binary format (the fastest for loading) but the same code would apply to xml with a different serializer.
using System.IO;
[Serializable]
class salesman
{
public string name, address, email;
public int sales;
}
class Program
{
static void Main(string[] args)
{
List<salesman> salesmanList = new List<salesman>();
string dir = #"c:\temp";
string serializationFile = Path.Combine(dir, "salesmen.bin");
//serialize
using (Stream stream = File.Open(serializationFile, FileMode.Create))
{
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bformatter.Serialize(stream, salesmanList);
}
//deserialize
using (Stream stream = File.Open(serializationFile, FileMode.Open))
{
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
List<salesman> salesman = (List<salesman>)bformatter.Deserialize(stream);
}
}
}
I just wrote a blog post on saving an object's data to Binary, XML, or Json; well writing an object or list of objects to a file that is. Here are the functions to do it in the various formats. See my blog post for more details.
Binary
/// <summary>
/// Writes the given object instance to a binary file.
/// <para>Object type (and all child types) must be decorated with the [Serializable] attribute.</para>
/// <para>To prevent a variable from being serialized, decorate it with the [NonSerialized] attribute; cannot be applied to properties.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the XML file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the XML file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
{
using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
binaryFormatter.Serialize(stream, objectToWrite);
}
}
/// <summary>
/// Reads an object instance from a binary file.
/// </summary>
/// <typeparam name="T">The type of object to read from the XML.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the binary file.</returns>
public static T ReadFromBinaryFile<T>(string filePath)
{
using (Stream stream = File.Open(filePath, FileMode.Open))
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
return (T)binaryFormatter.Deserialize(stream);
}
}
XML
Requires the System.Xml assembly to be included in your project.
/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
var serializer = new XmlSerializer(typeof(T));
reader = new StreamReader(filePath);
return (T)serializer.Deserialize(reader);
}
finally
{
if (reader != null)
reader.Close();
}
}
Json
You must include a reference to Newtonsoft.Json assembly, which can be obtained from the Json.NET NuGet Package.
/// <summary>
/// Writes the given object instance to a Json file.
/// <para>Object type must have a parameterless constructor.</para>
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite);
writer = new StreamWriter(filePath, append);
writer.Write(contentsToWriteToFile);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an Json file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the Json file.</returns>
public static T ReadFromJsonFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
reader = new StreamReader(filePath);
var fileContents = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(fileContents);
}
finally
{
if (reader != null)
reader.Close();
}
}
Example
// Write the list of salesman objects to file.
WriteToXmlFile<List<salesman>>("C:\salesmen.txt", salesmanList);
// Read the list of salesman objects from the file back into a variable.
List<salesman> salesmanList = ReadFromXmlFile<List<salesman>>("C:\salesmen.txt");
If you want to use JSON then using Json.NET is usually the best way to go.
If for some reason you are unable to use Json.NET you can use the built in JSON support found in .NET.
You will need to include the following using statement and add a reference for System.Web.Extentsions.
using System.Web.Script.Serialization;
Then you would use these to Serialize and Deserialize your object.
//Deserialize JSON to your Object
YourObject obj = new JavaScriptSerializer().Deserialize<YourObject>("File Contents");
//Serialize your object to JSON
string sJSON = new JavaScriptSerializer().Serialize(YourObject);
https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer_methods(v=vs.110).aspx
If you want xml serialization, you can use the built-in serializer. To achieve this, add [Serializable] flag to the class:
[Serializable()]
class salesman
{
public string name, address, email;
public int sales;
}
Then, you could override the "ToString()" method which converts the data into xml string:
public override string ToString()
{
string sData = "";
using (MemoryStream oStream = new MemoryStream())
{
XmlSerializer oSerializer = new XmlSerializer(this.GetType());
oSerializer.Serialize(oStream, this);
oStream.Position = 0;
sData = Encoding.UTF8.GetString(oStream.ToArray());
}
return sData;
}
Then just create a method that writes this.ToString() into a file.
UPDATE
The mentioned above will serialize single entry as xml. If you need the whole list to be serialized, the idea would be a bit different. In this case you'd employ the fact that lists are serializable if their contents are serializable and use the serialization in some outer class.
Example code:
[Serializable()]
class salesman
{
public string name, address, email;
public int sales;
}
class salesmenCollection
{
List<salesman> salesmanList;
public void SaveTo(string path){
System.IO.File.WriteAllText (path, this.ToString());
}
public override string ToString()
{
string sData = "";
using (MemoryStream oStream = new MemoryStream())
{
XmlSerializer oSerializer = new XmlSerializer(this.GetType());
oSerializer.Serialize(oStream, this);
oStream.Position = 0;
sData = Encoding.UTF8.GetString(oStream.ToArray());
}
return sData;
}
}

Serialize and Deserialize object graph using BinaryFormatter

I'm trying to serialize my object graph to a string then deserialize it from a string. The object serializes just fine if I do this
using (var memStream = new System.IO.MemoryStream())
{
mf.Serialize(memStream, this);
memStream.Seek(0, 0);
Search s;
using (var memStrClone = new System.IO.MemoryStream())
{
memStream.CopyTo(memStrClone);
memStrClone.Seek(0, 0);
s = mf.Deserialize(memStrClone) as Search;
}
}
The above code works but serializing to a string and trying to deserialize that same string like this
Search s;
string xml = ToString<Search>(this);
s = FromString<Search>(xml);
public static TType FromString<TType>(string input)
{
var byteArray = Encoding.ASCII.GetBytes(input);
using (var stream = new MemoryStream(byteArray))
{
var bf = new BinaryFormatter();
return (TType)bf.Deserialize(stream);
}
}
public static string ToString<TType>(TType data)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, data);
return Encoding.ASCII.GetString(ms.GetBuffer());
}
}
Throws an exception
No assembly ID for object type '1936026741 Core.Sebring.BusinessObjects.Search.Search'.
Any help is greatly appreciated. Thanks.
Here is some code which will do what you want to to (I think) - but I've got to ask - why do you want to serialize to a string like that?
If the class is simple enough to serialise to a string, use an XML serializer which is much easier to deal with; if you want to serialize it out to disk, binary write it out to a file and if it is complicated and you are serializing it to transmit - consider using something like protobuf-net.
I think the crux of your problem is that you are trying to use ASCII encoding - I'm using Base64 encoding.
Anyway - here goes (I've just had a guess at your Search class!)
class Program
{
[Serializable]
public class Search
{
public Guid ID { get; private set; }
public Search() { }
public Search(Guid id)
{
ID = id;
}
public override string ToString()
{
return ID.ToString();
}
}
static void Main(string[] args)
{
Search search = new Search(Guid.NewGuid());
Console.WriteLine(search);
string serialized = SerializeTest.SerializeToString(search);
Search rehydrated = SerializeTest.DeSerializeFromString<Search>(serialized);
Console.WriteLine(rehydrated);
Console.ReadLine();
}
}
public class SerializeTest
{
public static Encoding _Encoding = Encoding.Unicode;
public static string SerializeToString(object obj)
{
byte[] byteArray = BinarySerializeObject(obj);
return Convert.ToBase64String(byteArray);
}
public static T DeSerializeFromString<T>(string input)
{
byte[] byteArray = Convert.FromBase64String(input);
return BinaryDeserializeObject<T>(byteArray);
}
/// <summary>
/// Takes a byte array and deserializes it back to its type of <see cref="T"/>
/// </summary>
/// <typeparam name="T">The Type to deserialize to</typeparam>
/// <param name="serializedType">The object as a byte array</param>
/// <returns>The deserialized type</returns>
public static T BinaryDeserializeObject<T>(byte[] serializedType)
{
if (serializedType == null)
throw new ArgumentNullException("serializedType");
if (serializedType.Length.Equals(0))
throw new ArgumentException("serializedType");
T deserializedObject;
using (MemoryStream memoryStream = new MemoryStream(serializedType))
{
BinaryFormatter deserializer = new BinaryFormatter();
deserializedObject = (T)deserializer.Deserialize(memoryStream);
}
return deserializedObject;
}
/// <summary>
/// Takes an object and serializes it into a byte array
/// </summary>
/// <param name="objectToSerialize">The object to serialize</param>
/// <returns>The object as a <see cref="byte"/> array</returns>
public static byte[] BinarySerializeObject(object objectToSerialize)
{
if (objectToSerialize == null)
throw new ArgumentNullException("objectToSerialize");
byte[] serializedObject;
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, objectToSerialize);
serializedObject = stream.ToArray();
}
return serializedObject;
}
}
HTH

Categories