I'm trying to serialize a FormCollection object, and based on what I have researched, it inherits NameObjectCollectionBase so it also inherits GetObjectData and ISerializable. Wouldn't this mean it is serializable?
https://msdn.microsoft.com/en-us/library/system.web.mvc.formcollection(v=vs.118).aspx
Here's a snippet of what I'm trying:
BinaryFormatter formatter = new BinaryFormatter();
//Serialize
using (MemoryStream stream = new MemoryStream())
{
formatter.Serialize(stream, data);
string test = Convert.ToBase64String(stream.ToArray());
Session["test"] = test;
};
//Deserialize
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String((string)Session["test"])))
{
data = (FormCollection) formatter.Deserialize(stream);
}
I, unfortunately, got this error:
System.Runtime.Serialization.SerializationException: Type 'System.Web.Mvc.FormCollection' in Assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral... is not marked as serializable.
Because this is a sealed class, I cannot extend it and add the [Serializable] Attribute.
My questions is:
Why I can't serialize FormCollection like this?
And how I can serialize/deserialize a FormCollection object?
It cannot be serialized like this because it lacks [Serializable] attribute. That means developers of this class had no intention to make it serializable (with BinaryFormatter). The fact it's parent class implements ISerializable and marked with [Serializable] does not change anything - child class might have it's own internal details which will be lost during serialization if it was allowed to serialize any descendant of serializable class.
If you want to use BinaryFormatter (which might or might not be the best way) - you can do it like this:
BinaryFormatter formatter = new BinaryFormatter();
//Serialize
string serialized;
using (MemoryStream stream = new MemoryStream())
{
// pass FormCollection to constructor of new NameValueCollection
// that way we kind of convert it to NameValueCollection which is serializable
// of course we lost any FormCollection-specific details (if there were any)
formatter.Serialize(stream, new NameValueCollection(data));
serialized = Convert.ToBase64String(stream.ToArray());
};
//Deserialize
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(serialized))) {
// deserialize as NameValueCollection then create new
// FormCollection from that
data = new FormCollection((NameValueCollection) formatter.Deserialize(stream));
}
Related
I'm working with some highly custom objects from a nuget package that I need to store in the local SQLite db using Xamarin. I tried using this code
public static byte[] Serialize(ComplexType c)
{
byte[] arrayData;
using(MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize( stream, c );
arrayData = stream.ToArray();
stream.Close();
}
return arrayData;
}
public static ComplexType Deserialize(byte[] arrayData)
{
ComplexType c;
using(MemoryStream stream = new MemoryStream())
{
stream.Write( arrayData, 0, arrayData.Length );
stream.Seek( 0, SeekOrigin.Begin );
BinaryFormatter formatter = new BinaryFormatter();
c = (ComplexType) formatter.Deserialize( stream );
}
return c;
}
to serialize and store the object then retrieve it and deserialize it. It seems like it worked fine to do the serialization but now it turns out that the object is not marked serializable. I can't add the SerializableAttribute property to it because it's from a nuget. I tried editing the object definition in the nuget but of course it's locked.
Is there any easy way to pull off serializing an object not marked serializable or perhaps some other simple method of storing a non-serializable custom object in a SQLite database? Or should I just byte the bullet and write really complicated setters and getters to store all of the custom object's individual custom properties broken down into their individual lists of standard properties and basically deconstruct and reconstruct the object every time it goes to and from the database?
I'm seeing mixed reports on ISerializable and derived classes. Will implementing ISerializable on a derived class from the custom object allow the derived class to be serialized? What about IXMLSerializable? Will either of these work? I just want to get some clarification if possible before I go way down the wrong rabbit hole.
I've been getting an error during deserialization:
SerializationException: Could not find type 'System.Collections.Generic.List`1[[ExampleNamespace.ExampleClass, Assembly-CSharp, Version=0.1.6279.22118, Culture=neutral, PublicKeyToken=null]]'.
First I have serialized a custom [Serializable] class (saveStructure):
BinaryFormatter formatter = new BinaryFormatter();
FileStream file = File.Open(saveFilePath, FileMode.Open);
formatter.Serialize(file, saveStructure);
file.Close();
Which contains a few fields along with a List<ExampleClass> field.
MyCustomClass is also a [Serializable] class.
It seems to serialize the structure properly, but can not read it back during deserialization:
BinaryFormatter formatter = new BinaryFormatter();
FileStream file = File.Open(saveFilePath, FileMode.Open);
SaveStructure saveStructure = (SaveStructure)formatter.Deserialize(file);
file.Close();
I am aware of XmlSerializer, however I do not want to expose the data to the users.
Thanks in advance!
Edit:
I have solved my problem by using Arrays instead of Lists, however, if someone is to offer a solution for the List problem, I'd still be grateful!
Let's say I have
List<object> mainList = new List<object>();
And it contains
List<string> stringList = new List<string();
List<CustomClass> custList = new List<CustomClass>();
mainList.Add(stringList);
mainList.Add(custList);
To serialize
Stream stream;
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, mainList);
To deserialize
Stream stream = (Stream)o;
BinaryFormatter formatter = new BinaryFormatter();
List<object> retrievedList = (List<object>)formatter.Deserialize(stream);
At this point, I receive an error that the stream read (deserialization) reached the end of the stream without retrieving a value.
Do I need to specify something besides...
[Serializable]
public class CustomClass { .... }
in the custom class to make this work? Can I not deserialize a List> that contains different type of object every time?
I tried
IList list = (IList)Activator.CreateInstance(typeof(custClassList[0]))
and tried to send and receive this, but got the same issue.
I can however serialize and deserialize a specified type or List, but I really need it to be dynamic.
Basically, BinaryFormatter is a joke. It works in some cases, but will fail in almost identical scenarios for unknown reasons.
The best and superior alternative to BinaryFormatter is the third-party library protobuf-net (https://github.com/mgravell/protobuf-net), developed by Marc Gravel.
This beauty solved all the problems I was having in one pass. It's much easier to set up and reacts more perfectly to complex, custom classes.
I should also mention that it's faster, in the terms of de/serialization.
In order to fix the issue that causes the error "stream read (deserialization) reached the end of the stream ", the stream position needs to reset to 0 as follows...
stream.Position = 0;
Do I need to specify something besides...
[Serializable] public class CustomClass { .... }
Nope...That should be good for what you are doing.
in the custom class to make this work? Can I not deserialize a List>
that contains different type of object every time?
You should be able to serialize any object.
I have an object, instance of a Serializable class. I was wondering how can you get this object as a byte stream?
I know I can use BinaryFormatter and then use the Serialize method, but this method takes a serializationStream where it writes the serialized object. I want to be able to write it in a file/stream in a specific position so I would like to do something like:
obj = new Something(); // obj is serializable
byte[] serialized = obj.serialize(); [*]
file.write(position, serialized)
Is there any way I can do the [*], to take the bytes of the serialization of an object?
MemoryStream m = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(m, new MyClass() {Name="SO"});
byte[] buf = m.ToArray(); //or File.WriteAllBytes(filename, m.ToArray())
[Serializable]
public class MyClass
{
public string Name;
}
I need to save an object, its serializable but I donot want to use XML.
Is it possible to write the raw bytes of the object and then read it off the disk to create the object again?
Thanks for the help!
Use a BinaryFormatter:
var formatter = new BinaryFormatter();
// Serialize
using (var stream = File.OpenWrite(path))
{
formatter.Serialize(stream, yourObject);
}
...
// Deserialize
using (var stream = File.OpenRead(path))
{
YourType yourObject = (YourType)formatter.Deserialize(stream);
}
Yes, it is called binary serialization. There are some good examples on the MSDN site:
http://msdn.microsoft.com/en-us/library/4abbf6k0(v=vs.100).aspx