views:

2393

answers:

9

An application I've been working with is failing when i try to serialize types.

A statement like this:

XmlSerialzer lizer = new XmlSerializer(typeof(MyType));

Produces:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  FusionLog=""
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)

I don't define any special serializers for my class.

A: 

Troubleshooting compilation errors on the other hand is very complicated. These problems manifest themselves in a FileNotFoundException with the message:

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
   at System.Reflection.Assembly.nLoad( ... )
   at System.Reflection.Assembly.InternalLoad( ... )
   at System.Reflection.Assembly.Load(...)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly()

You may wonder what a file not found exception has to do with instantiating a serializer object, but remember: the constructor writes C# files and tries to compile them. The call stack of this exception provides some good information to support that suspicion. The exception occurred while the XmlSerializer attempted to load an assembly generated by CodeDOM calling the System.Reflection.Assembly.Load method. The exception does not provide an explanation as to why the assembly that the XmlSerializer was supposed to create was not present. In general, the assembly is not present because the compilation failed, which may happen because, under rare circumstances, the serialization attributes produce code that the C# compiler fails to compile.

Note This error also occurs when the XmlSerializer runs under an account or a security environment that is not able to access the temp directory.

Source: http://msdn.microsoft.com/en-us/library/aa302290.aspx

Zyphrax
you don't get compilation errors at runtime...
SpaceghostAli
he didn't specify that this happend at runtime. Another thing I can think of is that you perhaps have a namespace/class conflict. What's the full name of your MyType?
Zyphrax
Yeah, I checked out ur link, the info on constructors, though helpful, wasn't what i needed.
Irwin
@SpaceghostAl You can compile at runtime. And that's what XmlSerializer does. It dynamically constructs at runtime an assembly that (de)serialize XML for the particular type.For whatever reason this process fails for the OP. Propably because of permission problems e.g. on a temp directory. (Could be as silly as out of disk space even.)
nos
Are you sure about this? I was pretty sure that the serialisation stuff gets compiled into an assembly with a name YourAssemblyName.XmlSerializers.dll *during the build*, not compiled at runtime. This could fail for all sorts of reasons, least of all NTFS permissions in the deployment folder.
tomfanning
I hate out of diskspace and failing to compile the XmlSerializer on the fly. You don't get any say on where it does this runtime compile!
Greg Domjan
+2  A: 

In Visual Studio project properties ("Build" page, if I recall it right) there is an option saying "generate serialization assembly". Try turning it on for a project that generates [Containing Assembly of MyType].

VladV
If only I could vote this up again...
Rowland Shaw
A: 

You type may reference other assemblies which cannot be found neither in the GAC nor in your local bin folder ==> ...

"or one of its dependencies. The system cannot find the file specified"

Can you give an example of the Type you want to serialize

Note: Ensure that your Type implements Serializable

Henrik
+3  A: 

Beleive it or not, this is normal behaviour. An exception is thrown but handled by the XmlSerializer, so if you just ignore it everything should continue on fine.

I have found this very anoying, there have been many complaints about this if you search around a bit but from what I've read Microsoft don't plan on doing anything about it.

You can avoid getting Exception popups all the time while debugging if you switch off first chance exceptions for that specific exception. In visual studio go to Debug -> Exceptions (or press CTRL+ALT+E), Common Language Runtime Exceptions -> System.IO -> System.IO.FileNotFoundException.

You can find information about another way around here:

http://bloggingabout.net/blogs/rick/archive/2005/03/01/2333.aspx

Martin Sherburn
One of the possible ways to get rid of this problem is check "Just my code" option in Tools -> Options -> Debugging -> General options.
Frederic
A: 

A custome Class to serialise.

[Serializable]
public class TestClass
{
    int x = 2;
    int y = 4;
    public TestClass(){}
    public TestClass(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int TestFunction()
    {
        return x + y;
    }
}

I have attached the code snippet, my be this can help you out.

        static void Main(string[] args)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));

            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

            TestClass domain = new TestClass(10, 3);
            xmlSerializer.Serialize(xmlWriter, domain);
            memoryStream = (MemoryStream)xmlWriter.BaseStream;
            string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray());

            TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString);

            Console.WriteLine(xmlDomain.TestFunction().ToString());
            Console.ReadLine();
        }
Tumbleweed
-1 for no using blocks to prevent resource leaks, and for using XmlTextWriter.
John Saunders
ok agree, but still I have used XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass)); but I'm not getting the said Exception.
Tumbleweed
+2  A: 

Like Martin Sherburn said, this is normal behavior. The constructor of the XmlSerializer first tries to find an assembly named [YourAssembly].XmlSerializers.dll which should contain the generated class for serialization of your type. Since such a DLL has not been generated yet (they are not by default), a FileNotFoundException is thrown. When that happenes, XmlSerializer's constructor catches that exception, and the DLL is generated automatically at runtime by the XmlSerializer's constructor (this is done by generating C# source files in the %temp% directory of your computer, then compiling them using the C# compiler). Additional constructions of an XmlSerializer for the same type will just use the already generated DLL.

The exception is handled by XmlSerializer's constructor. There is no need to do anything yourself, you can just click 'Continue' (F5) to continue executing your program and everything will be fine. If you're bothered by the exceptions stopping the execution of your program and popping up an exception helper, you either have 'Just My Code' turned off, or you have the FileNotFoundException set to break execution when thrown, instead of when 'User-unhandled'.

To enable 'Just My Code', go to Tools >> Options >> Debugging >> General >> Enable Just My Code. To turn off breaking of execution when FileNotFound is thrown, go to Debug >> Exceptions >> Find >> enter 'FileNotFoundException' >> untick the 'Thrown' checkbox from System.IO.FileNotFoundException.

Allon Guralnek
+1  A: 

This exception can also be trapped by an MDA called BindingFailure.

This MDA is useful if your application is designed to ship with pre-build serialization assemblies. We do this to increase performance for our application. It allows us to make sure that the pre-built serialization assemblies are being properly built by our build process, and loaded by the application without being re-built on the fly.

It's really not useful except in this scenario, because as other posters have said, when a binding error is trapped by the Serializer constructor, the serialization assembly is re-built at runtime. So you can usually turn it off.

HiredMind
+1  A: 

To avoid the exception you need to do two things:

  1. Add an attribute to the serialized class (I hope you have access)
  2. Generate the serialization file with sgen.exe

Add the System.Xml.Serialization.XmlSerializerAssembly attribute to your class. Replace 'MyAssembly' with the name of the assembly where MyClass is in.

[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{
…
}

Generate the serialization file using the sgen.exe utility and deploy it with the class’s assembly.

‘sgen.exe MyAssembly.dll’ will generate the file MyAssembly.XmlSerializers.dll

These two changes will cause the .net to directly find the assembly. I checked it and it works on .NET framework 3.5 with Visual Studio 2008

Ami Bar
Ok, and did it fail without these changes, and if so, why?
John Saunders
A: 

In Visual Studio project properties there is an option saying "generate serialization assembly". Try turning it on for a project that generates [Containing Assembly of MyType].

Pascal