Problem with BinaryFormatter Deserialize method

J

Joe Cool

I have this class in a project:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Text;

namespace myProject
{
[Serializable]
public class Attachment
{

#region class variables

ArrayList _fields = null;
string _application;
int _docid;

#endregion


#region contructors

public Attachment()
{
_fields = new ArrayList();
_application = string.Empty;
_docid = 0;
}

#endregion


#region properties

public string Application
{
get { return _application; }
set { _application = value; }
}

public ArrayList Fields
{
get { return _fields; }
set { _fields = value; }
}

public int DocID
{
get { return _docid; }
set { _docid = value; }
}

#endregion


#region public methods

public byte[] Serialize()
{
MemoryStream memoryStream = null;
BinaryFormatter formatter = null;

try
{
memoryStream = new MemoryStream();

formatter = new BinaryFormatter();

formatter.Serialize(memoryStream, this);

return memoryStream.ToArray();
}
catch (Exception ex)
{
return null;
}
finally
{
memoryStream.Close();
}
}

public void Deserialize(byte[] attachmentBytes)
{
BinaryFormatter formatter = null;
MemoryStream memoryStream = null;
Attachment tempAttachment = null;
object tempObject = null;

try
{
formatter = new BinaryFormatter();

memoryStream = new MemoryStream(attachmentBytes);

formatter.Binder = new GenericBinder();

memoryStream.Position = 0;

tempObject = formatter.Deserialize(memoryStream);

tempAttachment = (Attachment)tempObject;

this.Application = tempAttachment.Application;
this.Fields = tempAttachment.Fields;
this.DocID = tempAttachment.DocID;
}
catch(Exception ex)
{
return;
}
}

#endregion

}
}

When I try to invoke the Deserialize on a byte array that I just
serialized, it throws this exception:

Binary stream '0' does not contain a valid BinaryHeader. Possible
causes are invalid stream or object version change between
serialization and deserialization.

I have googled t his exception and cannot find any solution that fixes
my problem. Any help would be appreciated.
 
P

Peter Duniho

[...]
When I try to invoke the Deserialize on a byte array that I just
serialized, it throws this exception:

Binary stream '0' does not contain a valid BinaryHeader. Possible
causes are invalid stream or object version change between
serialization and deserialization.

I have googled t his exception and cannot find any solution that fixes
my problem. Any help would be appreciated.

Most likely, you have made a mistake either with the bytes being
deserialized, or the GenericBinder() class is doing something odd.

Since you didn't post the specifics regarding either of those aspects,
never mind a concise-but-complete code example that reliably reproduces
the problem, there's no way for anyone to say for sure what's wrong.

Pete
 
J

Joe Cool

[...]
When I try to invoke the Deserialize on a byte array that I just
serialized, it throws this exception:
Binary stream '0' does not contain a valid BinaryHeader. Possible
causes are invalid stream or object version change between
serialization and deserialization.
I have googled t his exception and cannot find any solution that fixes
my problem. Any  help would be appreciated.

Most likely, you have made a mistake either with the bytes being  
deserialized, or the GenericBinder() class is doing something odd.

Since you didn't post the specifics regarding either of those aspects,  
never mind a concise-but-complete code example that reliably reproduces  
the problem, there's no way for anyone to say for sure what's wrong.

Pete

WIll this help? Here is the GenericBinder class:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Text;

namespace myProject
{
public class GenericBinder : SerializationBinder
{
/// <summary>
/// Resolve type
/// </summary>
/// <param name="assemblyName">eg. App_Code.y4xkvcpq,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</param>
/// <param name="typeName">eg. String</param>
/// <returns>Type for the deserializer to use</returns>
public override Type BindToType(string assemblyName, string
typeName)
{
// We're going to ignore the assembly name, and assume
it's in the same assembly
// that <T> is defined (it's either T or a field/return
type within T anyway)
string[] typeInfo = typeName.Split('.');
bool isSystem = (typeInfo[0].ToString() == "System");
string className = typeInfo[typeInfo.Length - 1];

// noop is the default, returns what was passed in
Type toReturn = Type.GetType(string.Format("{0}, {1}",
typeName, assemblyName));

if (!isSystem && (toReturn == null))
{ // don't bother if system, or if the GetType worked
already (must be OK, surely?)
System.Reflection.Assembly a =
System.Reflection.Assembly.GetAssembly(typeof(Attachment));
if (a == null)
{
throw new ArgumentException("Assembly for type '"
+ typeof(Attachment).Name.ToString() + "' could not be loaded.");
}
else
{
string assembly = a.FullName.Split(',')[0]; //
FullName example: "App_Code.y4xkvcpq, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null"
Type newtype = a.GetType(assembly + "." +
className);
if (newtype == null)
{
throw new ArgumentException("Type '" +
typeName + "' could not be loaded from assembly '" + assembly + "'.");
}
else
{
toReturn = newtype;
}
}
}
return toReturn;
}
}
}
 
J

Joe Cool

[...]
When I try to invoke the Deserialize on a byte array that I just
serialized, it throws this exception:
Binary stream '0' does not contain a valid BinaryHeader. Possible
causes are invalid stream or object version change between
serialization and deserialization.
I have googled t his exception and cannot find any solution that fixes
my problem. Any  help would be appreciated.

Most likely, you have made a mistake either with the bytes being  
deserialized, or the GenericBinder() class is doing something odd.

Since you didn't post the specifics regarding either of those aspects,  
never mind a concise-but-complete code example that reliably reproduces  
the problem, there's no way for anyone to say for sure what's wrong.

Pete

Oh, and the bytes being deserialized was a byte array that had been
generated by this same class's Serialize method, stored in a database
as a byte array, and later retrieved for Deserialization.
 
J

Joe Cool

WIll this help? Here is the GenericBinder class: [...]

Here are some links you may find helpful:http://www.yoda.arachsys.com/csharp.../csharp/incomplete.htmlhttp://sscce.org/(some Java-centric stuff, but mostly applicable to any  
programming questions)

Interesting reading. But none of it answers my original question. I
just cut and pasted the entire class. I did not write this, I was told
to make some mods to another class in the project and this problem
cropped up. Obviously the person who wrote that class cut and pasted
the code from somewhere else and modified for our specific needs.
 
P

Peter Duniho

Interesting reading. But none of it answers my original question.

Correct. The goal of those links are not to answer your original
question, but to provide you with the information you need in order to ask
a question that can be answered.
 
J

Joe Cool

Correct.  The goal of those links are not to answer your original  
question, but to provide you with the information you need in order to ask  
a question that can be answered.

I am still missing your point. From what I can tell, the only problem
with what I posted was that I included a bunch on comments in the
Generic Binder class post. But jeez, how does that mean that I have
asked a question that cannot be answered.

You asked for more details, I provided them. What's the problem?
 
P

Peter Duniho

I am still missing your point.

I am unable to explain my point any better than the web pages to which I
referred you.
From what I can tell, the only problem
with what I posted was that I included a bunch on comments in the
Generic Binder class post.

That may be as much as you can tell, but it's far from the only problem.
But jeez, how does that mean that I have
asked a question that cannot be answered.

If someone here cannot take a verbatim copy of the code you post, paste it
into an empty file, and then compile and execute that file without _any_
additional work, then you have not posted the necessary
concise-but-complete code example.

In some cases a question is so simple that someone can easily infer enough
information to complete the question and answer it in spite of the lack of
appropriate detail in the question. But this is not one of those cases.
You asked for more details, I provided them. What's the problem?

I didn't simply ask "for more details". I asked for a specific kind of
detail, which you have not yet provided.

I suspect that in the end, you will find that you are somehow managing to
not provide the exact same bytes to the deserialize method as were
produced in the serialize method. But until you provide an appropriate
code example, there's no way to verify that, or even to say for sure
that's actually the problem.

Pete
 
F

Family Tree Mike

Joe said:
I am still missing your point. From what I can tell, the only problem
with what I posted was that I included a bunch on comments in the
Generic Binder class post. But jeez, how does that mean that I have
asked a question that cannot be answered.

You asked for more details, I provided them. What's the problem?

I believe the point is that it may help if you show a main subroutine
that 1) creates the object, 2) serializes it, and 3) deserializes it.
One reason being is, that with the following, I don't observe what you
are asking about.

public static void Main(string [] args)
{
Attachment a = new Attachment();
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, a);
ms.Seek(0, SeekOrigin.Begin);

Attachment b;
b = (Attachment) bf.Deserialize(ms);
Console.WriteLine("Done");
Console.ReadKey();
}
 
J

Joe Cool

I am still missing your point. From what I can tell, the only problem
with what I posted was that I included a bunch on comments in the
Generic Binder class post. But jeez, how does that mean that I have
asked a question that cannot be answered.
You asked for more details, I provided them. What's the problem?

I believe the point is that it may help if you show a main subroutine
that 1) creates the object, 2) serializes it, and 3) deserializes it.
One reason being is, that with the following, I don't observe what you
are asking about.

         public static void Main(string [] args)
         {
             Attachment a = new Attachment();
             BinaryFormatter bf = new BinaryFormatter();
             MemoryStream ms = new MemoryStream();
             bf.Serialize(ms, a);
             ms.Seek(0, SeekOrigin.Begin);

             Attachment b;
             b = (Attachment) bf.Deserialize(ms);
             Console.WriteLine("Done");
             Console.ReadKey();
         }

Yes, I understand's Peter's criticism now. Since I did not want to
post any company proprietary code I wrote a console app to demonstrate
the problem and lo and behold, it worked fine.

Turns out I was depending on some third party software to properly
store the byte array in a database and return it to me in its original
format. But they were not storing the very last byte. Their software
returned to me the correct number of bytes but the last byte was now
zero instead of the value I was expecting it to be.

Lesson learned: don't assume third party software is going to work as
you expect it to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top