Serialize and Deserialize object graph using BinaryFormatter - c#

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

Related

Serialize/deserialize without external library in c#

How do i serialize/de serialize JSON data in c# without using any library or nugget package
i tried this
it allways shows me error!
{
/// <summary>
/// Deserialize an from json string
/// </summary>
public static T Deserialize<T>(string body)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
{
writer.Write(body);
writer.Flush();
stream.Position = 0;
return (T)new DataContractJsonSerializer(typeof(T)).ReadObject(stream);
}
}
/// <summary>
/// Serialize an object to json
/// </summary>
public static string Serialize<T>(T item)
{
using (MemoryStream ms = new MemoryStream())
{
new DataContractJsonSerializer(typeof(T)).WriteObject(ms, item);
return Encoding.Default.GetString(ms.ToArray());
}
}
}```
System.Text.Json as a library from Microsoft and Newtonsoft.Json, an external serializer friend.
Dotnet has a library for your request Source page
string jsonString = JsonSerializer.Serialize(weatherForecast);
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);

Rest transfer non serializable objects

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;
}
}
}

C# Loading in Data with XML File [duplicate]

I'm basically looking for someone to point me in the right direction on this. I read through some of the Microsoft documentation, but that wasn't very helpful. This is my first attempt at working with XML.
I'm writing an application that needs to store a list of known users and a list of aliases created by each of those users. I've figured out how to have my lists serialized and stored to XML files when the application closes and have it retrieve those when the application opens again, but I don't want to keep the list of users and aliases in memory.
In order for this to work, I need to have the ability to search, edit, and append to the XML file during run time.
The XML structure I envision is something like:
<UserRecord>
<User>Username-1</User>
<AliasRecord>
<Alias>Alias-1</Alias>
<Number>6135551234</Number>
</AliasRecord>
<AliasRecord>
<Alias>Alias-2</Alias>
<Number>6131238888</Number>
</AliasRecord>
</UserRecord>
Each user would only have one username but could have multiple aliases. I need to have the ability to add users, add aliases to a new or existing user, and change existing aliases. Usernames would never change, but an entire User record could be deleted.
So far, the only XML I've done in C# uses serialization but I don't think that approach will work for the above.
private void WriteXML()
{
try
{
System.Xml.Serialization.XmlSerializer XMLwriter = new System.Xml.Serialization.XmlSerializer(typeof(MessageRecord));
System.IO.StreamWriter XMLfile = new System.IO.StreamWriter("Saved MessageRecords.xml");
foreach (MessageRecord mr in OutgoingMessages)
{
XMLwriter.Serialize(XMLfile, mr);
}
XMLfile.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
Create two classes to represent UserRecord and AliasRecord.
public class UserRecord
{
public string User { get; set; }
public List<AliasRecord> AliasRecords { get; set; }
}
public class AliasRecord
{
public string Alias { get; set; }
public string Number { get; set; }
}
Populate them like this:
var userRecord = new UserRecord
{
User = "UserName1",
AliasRecord = new List<AliasRecord> {
new AliasRecord { Alias = "Alias1", Number = "12345678" },
new AliasRecord { Alias = "Alias2", Number = "23456789" }
}
};
And use this code to serialize/deserialize it:
public static class XmlHelper
{
public static bool NewLineOnAttributes { get; set; }
/// <summary>
/// Serializes an object to an XML string, using the specified namespaces.
/// </summary>
public static string ToXml(object obj, XmlSerializerNamespaces ns)
{
Type T = obj.GetType();
var xs = new XmlSerializer(T);
var ws = new XmlWriterSettings { Indent = true, NewLineOnAttributes = NewLineOnAttributes, OmitXmlDeclaration = true };
var sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb, ws))
{
xs.Serialize(writer, obj, ns);
}
return sb.ToString();
}
/// <summary>
/// Serializes an object to an XML string.
/// </summary>
public static string ToXml(object obj)
{
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
return ToXml(obj, ns);
}
/// <summary>
/// Deserializes an object from an XML string.
/// </summary>
public static T FromXml<T>(string xml)
{
XmlSerializer xs = new XmlSerializer(typeof(T));
using (StringReader sr = new StringReader(xml))
{
return (T)xs.Deserialize(sr);
}
}
/// <summary>
/// Deserializes an object from an XML string, using the specified type name.
/// </summary>
public static object FromXml(string xml, string typeName)
{
Type T = Type.GetType(typeName);
XmlSerializer xs = new XmlSerializer(T);
using (StringReader sr = new StringReader(xml))
{
return xs.Deserialize(sr);
}
}
/// <summary>
/// Serializes an object to an XML file. (Fixed code)
/// </summary>
public static void ToXmlFile(object obj, string filePath)
{
var xs = new XmlSerializer(obj.GetType());
var ns = new XmlSerializerNamespaces();
var ws = new XmlWriterSettings { Indent = true, NewLineOnAttributes = NewLineOnAttributes, OmitXmlDeclaration = true };
ns.Add("", "");
using (XmlWriter writer = XmlWriter.Create(filePath, ws))
{
xs.Serialize(writer, obj, ns);
}
}
/// <summary>
/// Deserializes an object from an XML file.
/// </summary>
public static T FromXmlFile<T>(string filePath)
{
StreamReader sr = new StreamReader(filePath);
try
{
var result = FromXml<T>(sr.ReadToEnd());
return result;
}
catch (Exception e)
{
throw new Exception("There was an error attempting to read the file " + filePath + "\n\n" + e.InnerException.Message);
}
finally
{
sr.Close();
}
}
}
Example usage:
var result = XmlHelper.ToXml(userRecord);
Result:
<UserRecord>
<User>Username1</User>
<AliasRecords>
<AliasRecord>
<Alias>Alias1</Alias>
<Number>12345678</Number>
</AliasRecord>
<AliasRecord>
<Alias>Alias2</Alias>
<Number>23456789</Number>
</AliasRecord>
</AliasRecords>
</UserRecord>

Serializing/deserializing with memory stream

I'm having an issue with serializing using memory stream. Here is my code:
/// <summary>
/// serializes the given object into memory stream
/// </summary>
/// <param name="objectType">the object to be serialized</param>
/// <returns>The serialized object as memory stream</returns>
public static MemoryStream SerializeToStream(object objectType)
{
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, objectType);
return stream;
}
/// <summary>
/// deserializes as an object
/// </summary>
/// <param name="stream">the stream to deserialize</param>
/// <returns>the deserialized object</returns>
public static object DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object objectType = formatter.Deserialize(stream);
return objectType;
}
The error I'm getting is as follow:
stream is not a valid binary format. The starting contents (in bytes) are: blah....
I'm not exactly sure what is causing the error. Any help would be greatly appreciated.
Example of the call:
Dog myDog = new Dog();
myDog.Name= "Foo";
myDog.Color = DogColor.Brown;
MemoryStream stream = SerializeToStream(myDog)
Dog newDog = (Dog)DeserializeFromStream(stream);
This code works for me:
public void Run()
{
Dog myDog = new Dog();
myDog.Name= "Foo";
myDog.Color = DogColor.Brown;
System.Console.WriteLine("{0}", myDog.ToString());
MemoryStream stream = SerializeToStream(myDog);
Dog newDog = (Dog)DeserializeFromStream(stream);
System.Console.WriteLine("{0}", newDog.ToString());
}
Where the types are like this:
[Serializable]
public enum DogColor
{
Brown,
Black,
Mottled
}
[Serializable]
public class Dog
{
public String Name
{
get; set;
}
public DogColor Color
{
get;set;
}
public override String ToString()
{
return String.Format("Dog: {0}/{1}", Name, Color);
}
}
and the utility methods are:
public static MemoryStream SerializeToStream(object o)
{
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, o);
return stream;
}
public static object DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object o = formatter.Deserialize(stream);
return o;
}
Use Method to Serialize and Deserialize Collection object from memory. This works on Collection Data Types. This Method will Serialize collection of any type to a byte stream. Create a Seperate Class SerilizeDeserialize and add following two methods:
public class SerilizeDeserialize
{
// Serialize collection of any type to a byte stream
public static byte[] Serialize<T>(T obj)
{
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter binSerializer = new BinaryFormatter();
binSerializer.Serialize(memStream, obj);
return memStream.ToArray();
}
}
// DSerialize collection of any type to a byte stream
public static T Deserialize<T>(byte[] serializedObj)
{
T obj = default(T);
using (MemoryStream memStream = new MemoryStream(serializedObj))
{
BinaryFormatter binSerializer = new BinaryFormatter();
obj = (T)binSerializer.Deserialize(memStream);
}
return obj;
}
}
How To use these method in your Class:
ArrayList arrayListMem = new ArrayList() { "One", "Two", "Three", "Four", "Five", "Six", "Seven" };
Console.WriteLine("Serializing to Memory : arrayListMem");
byte[] stream = SerilizeDeserialize.Serialize(arrayListMem);
ArrayList arrayListMemDes = new ArrayList();
arrayListMemDes = SerilizeDeserialize.Deserialize<ArrayList>(stream);
Console.WriteLine("DSerializing From Memory : arrayListMemDes");
foreach (var item in arrayListMemDes)
{
Console.WriteLine(item);
}
BinaryFormatter may produce invalid output in some specific cases. For example it will omit unpaired surrogate characters. It may also have problems with values of interface types. Read this documentation page including community content.
If you find your error to be persistent you may want to consider using XML serializer like DataContractSerializer or XmlSerializer.
It can be done easily by using System.Text.Json in .Net 6
using System.Text.Json;
Examlple ex = JsonSerializer.Deserialize<Example>(ms);
Console.WriteLine(ex.Value);
class Example
{
string Value {get; set; }
}
Refer to this for serialization.

trying to serialize and deserialize entity object in c#

I am using two methods below to serialize/deserialize entity framework object (ver. 4.0).
I tried several ways to accomplish this, and had no luck. Serialization works fine. I get nice xml formatted string, but when I try to deserialize I get error in XML. How is that possible?
Thanks.
public static string SerializeObject(Object obj)
{
XmlSerializer ser = new XmlSerializer(obj.GetType());
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter writer = new System.IO.StringWriter(sb);
ser.Serialize(writer, obj);
XmlDocument doc = new XmlDocument();
doc.LoadXml(sb.ToString());
string xml = doc.InnerXml;
return xml;
}
public static object DeSerializeAnObject(string xml, Type objType)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeReader reader = new XmlNodeReader(doc.DocumentElement);
XmlSerializer ser = new XmlSerializer(objType);
object obj = ser.Deserialize(reader);
return obj;
}
I use generic methods to serialize and deserialize:
/// <summary>
/// Serializes an object to Xml as a string.
/// </summary>
/// <typeparam name="T">Datatype T.</typeparam>
/// <param name="ToSerialize">Object of type T to be serialized.</param>
/// <returns>Xml string of serialized type T object.</returns>
public static string SerializeToXmlString<T>(T ToSerialize)
{
string xmlstream = String.Empty;
using (MemoryStream memstream = new MemoryStream())
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
XmlTextWriter xmlWriter = new XmlTextWriter(memstream, Encoding.UTF8);
xmlSerializer.Serialize(xmlWriter, ToSerialize);
xmlstream = UTF8ByteArrayToString(((MemoryStream)xmlWriter.BaseStream).ToArray());
}
return xmlstream;
}
/// <summary>
/// Deserializes Xml string of type T.
/// </summary>
/// <typeparam name="T">Datatype T.</typeparam>
/// <param name="XmlString">Input Xml string from which to read.</param>
/// <returns>Returns rehydrated object of type T.</returns>
public static T DeserializeXmlString<T>(string XmlString)
{
T tempObject = default(T);
using (MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(XmlString)))
{
XmlSerializer xs = new XmlSerializer(typeof(T));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
tempObject = (T)xs.Deserialize(memoryStream);
}
return tempObject;
}
// Convert Array to String
public static String UTF8ByteArrayToString(Byte[] ArrBytes)
{ return new UTF8Encoding().GetString(ArrBytes); }
// Convert String to Array
public static Byte[] StringToUTF8ByteArray(String XmlString)
{ return new UTF8Encoding().GetBytes(XmlString); }
i THINK the issue is with this line:
string xml = doc.InnerXml;
you want ALL the xml, not just the xml inside the root node.
Just return sb.ToString(), loading into the XmlDocument is not doing anything.
Some redundancies and usings was excluded. Refactored and cleaned up:
namespace MyProject
{
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
public static class Serializer
{
#region Public Methods and Operators
/// <summary>
/// Deserializes Xml string of type T.
/// </summary>
/// <typeparam name="T">Datatype T.</typeparam>
/// <param name="XmlString">Input Xml string from which to read.</param>
/// <returns>Returns rehydrated object of type T.</returns>
public static T DeserializeXmlString<T>(string xmlString)
{
T tempObject;
using (var memoryStream = new MemoryStream(StringToUTF8ByteArray(xmlString)))
{
var xs = new XmlSerializer(typeof(T));
tempObject = (T)xs.Deserialize(memoryStream);
}
return tempObject;
}
/// <summary>
/// Serializes an object to Xml as a string.
/// </summary>
/// <typeparam name="T">Datatype T.</typeparam>
/// <param name="toSerialize">Object of type T to be serialized.</param>
/// <returns>Xml string of serialized type T object.</returns>
public static string SerializeToXmlString<T>(T toSerialize)
{
string xmlstream;
using (var memstream = new MemoryStream())
{
var xmlSerializer = new XmlSerializer(typeof(T));
var xmlWriter = new XmlTextWriter(memstream, Encoding.UTF8);
xmlSerializer.Serialize(xmlWriter, toSerialize);
xmlstream = UTF8ByteArrayToString(((MemoryStream)xmlWriter.BaseStream).ToArray());
}
return xmlstream;
}
#endregion
#region Methods
private static byte[] StringToUTF8ByteArray(string xmlString)
{
return new UTF8Encoding().GetBytes(xmlString);
}
private static string UTF8ByteArrayToString(byte[] arrBytes)
{
return new UTF8Encoding().GetString(arrBytes);
}
#endregion
}
}

Categories