This page
Introduction to XMLSerializer internal working mode Serialized error declared the problem occurring when serialized type reverse sequence XML occurred from constructor abnormal summary
Introduction
The XMLSerializer in the .NET frame is a great tool that maps the highly structured XML data to the .NET object. XMLSerializer is called through a single API call in the program to perform the conversion between XML documents and objects. The converted mapping rules are represented by metadata properties in the .NET class. This programming model has its own error category, and developers need to learn how to diagnose these errors. For example, metadata properties must describe all variants of the XML format that serialization can process. This paper studies a variety of errors that may occur when using XMLSerializer to build an XML-based solution and discuss how tips and tools used to diagnose these errors.
Back to top
XMLSerializer's internal work mode
In order to effectively solve problems in the XML serialization process, you need to know what happened inside the very simple XMLSerializer interface. In contrast to traditional analysis modes, the XMLSERIALIZER of System.xml.Serialization namespace in the .NET framework binds the XML document to an instance of the .NET class. Programmers no longer need to write DOM or SAX analysis code, but declare the binding rules by adding .NET metadata properties directly in these classes. Because all analytical rules are represented by attributes, the interface of XMLSerializer is very simple. It consists mainly of two methods: serialize () is used to generate XML from an object instance; DeSerialize () is used to analyze the XML document into an object map.
This method is very effective when using strong types, perfectly mapped to the structure of the programmed object. If the format is defined by the W3C architecture, and the architecture consists of a ComplexType without a mixed content or without excessive using wildcard (XS: ANY and XS; Anyattribute), XML serialization is a good way to process the data.
A message-oriented application is a good example, and the exchange format between these applications is predefined. Because many news-driven enterprise applications have very high throughput requirements, the serialize () and DeserialIze () methods are designed to have high execution speed. In fact, it is the use of high scalability libraries with high scalability in the system.Messaging namespace, ASP.NET Web Services, and BizTalk Server 2004 provide power.
To obtain high performance of XMLSerializer, double cost is required. The first is the flexibility related to the XML format that is given to a given XMLSerializer, followed by the constructor of the instance, requires a lot of processing.
When you instantiate XMLSerializer, you must pass the type of object you attempt to serialize and deserialize the sequence of serialization. The serialization program will check all the public fields and properties of this type to understand which types are referenced at runtime. Next, it will create a C # code for a set of classes to use class processing serialization and deserialization in system.codedom namespace. In this process, XMLSerializer will check the reflection type of XML serialization properties to define classes from definitions based on the XML format. These classes are then compiled into a temporary assembly and is called by Serialize () and DeserialIze () method to perform XML to object transformation.
This setup process and declarative programming model of XMLSerializer have caused three types of errors, some of which may be difficult to resolve:
•
The generated serialization class is desirable to be serialized objects fully compliant the type structure defined by the metadata properties. If XMLSerializer encounters an unknown (explicit statement or by XML serialization attribute declaration), the object will not be serialized. •
The XML document cannot be reverse selecinstened in the following cases: the root element of this document cannot map object types; the format of this document is incorrect, such as characters defined as illegal in the XML specification; this document violates the infrastructure restrictions (in certain In the case of cases.
•
Finally, the creation of serialization and its subsequent compilation may fail due to a variety of different reasons. The class's creation may fail when it is transmitted to the type of constructor or the type referenced by this type, or when the XMLSERIALIZER is not satisfied.
When the additional attribute generates a C # code that cannot be compiled, the compilation step may fail. Compilation steps may also fail due to safety.
These situations will be further studied in depth and provide guidance and advice on how to solve these problems.
Back to top
Serialized error
The first type of error we have to study occurs in the serialize () method. Such errors occur when passing to the object diagram of the method at runtime and when the type declared in the design is not matched in the design. You can implicitly declare types through the type of field or attribute, or you can explicitly declare the type by additional serialization attribute.
Figure 1. Type declaration in the object map
It should be noted here that it is not enough to rely on inheritance. Developers must declare XMLSerializer's derived type by attaching the XMLInCludE property to the base class or by attaching the XMLELELEMENT property to fields (these fields can accommodate objects from the declared type of derived types).
For example, see the following class hierarchies:
Public Class Base
{
Public string field;
}
Public Class Derived
{
Public string anotherfield;
}
Public Class Container
{
Public Base Myfield;
}
If you rely on inheritance and write a sequential code similar to the following:
Container obj = new container ();
Obj.myfield = new derived (); // legal associternment in the
//.Net Type System
// ...
XMLSerializer Serializer = New XMLSerializer (TypeOf (Container);
Serializer.Serialize (Writer, Obj); // kaboom!
You will get an exception from the serialize () method because there is no XMLSerializer's explicit type declaration.
Pass from XMLSerializer
The root of diagnosis These issues may be more difficult at the beginning, because the exceptions from XMLSerializer do not provide a lot of information about it; at least, they do not provide information on the location where developers usually view.
In most cases, when an error occurs, Serialize, DeserialIze, and even the XMLSerializer constructor triggers a fairly ordinary system.invalidOperationException. This exception type can appear in many parts of the .NET framework; it is not unique to XMLSerializer. Worse, this exception's Message property produces only very common information. In the above example, the serialize () method will initiate an exception with the following message:
The "The XML Document. This message is also annoying, because when you see XMLSERIALIZER to trigger an exception, it has guess this. Now, you have to find that the unusually found that the unusual Message cannot help you solve the problem.
The strange abnormal message and the non-descriptive abnormal type reflect the XMLSeriRizer internal work mode as described earlier. The serialize () method captures all exceptions thrown in the serialization class, packing them into the InvalidOperationException, and then transmits the exception packet upwards up the stack.
Read exception message
The trick to get the "actual" exception information is to check the anomaly inNNeRexception property. Innerexception references the actual exception that caused from the serialization class. It contains very detailed information about this problem and its location. The exception captured when you run the above example will contain inNNeRexception with the following message:
The Type Derived Was NOT EXPECTED. Use the xmlinclude or soapinclude
Attribute to Specify Types That Are Not Known Staticly.
You can get this message by directly checking Innerexception or by calling this anomalous toString () method. The following code snippet demonstrates an exception handler, which writes information in all anomalies that occur during the process of deserialization:
Public void serializecontainer (XMLWRITER WRITER, Container Obj)
{
Try
{
// Make Sure Even the Construsctor Runs Inside A
// try-catch block
XMLSerializer Ser = New XMLSerializer (TypeOf (Container);
Ser.Serialize (Writer, Obj);
}
Catch (Exception EX)
{
DUMPEXCEPTION (EX);
}
}
Public Static Void Dumpexception (Exception EX)
{
Console.writeline ("------- Outer Exception Data ---------");
WriteExceptioninfo (ex);
EX = EX.INNNEREXCEPTION;
IF (NULL! = EX)
{
Console.writeline ("------- Inner Exception Data ---------");
WriteExceptioninfo (ex.innerexception);
EX = EX.INNNEREXCEPTION;
}
}
Public Static Void WriteExceptionInfo (Exception EX)
{
Console.writeline ("Message: {0}", EXMESSAGE);
Console.writeline ("Exception Type: {0}", ex.gettype (); fullname);
Console.writeline ("Source: {0}", EX.SOURCE);
Console.writeLine ("StrackTrace: {0}", EX.STACKTRACE;
Console.writeline ("Targetsite: {0}", EX.TARGETSITE);
}
Back to top
Declating Serialization Type To resolve issues in the above examples, you only need to read the INNEREXCEPTION message and implement the recommended solution. One field passed to the SERIALIZE method references a type of Derived object, but the field is not declared as a sequencer DeriveD type object. Although the object map is fully legal in the .NET type system, the XMLSerializer constructor is traversed by the field of the container type, and does not know the serialization code for the derived type object, because it did not find the derived type. Quote.
To declare additional fields and properties types to XMLSerializer, you have multiple options. You can declare the derived type on the base class by XMLinclude property (prompts), as shown below:
[System.xml.serialization.xmlinclude (Typeof (Derived)]
Public Class Base
{
// ...
}
By attaching the XMLinClude property, you can let XMLSerializer are defined as the field of the DeriveD type object when the field or attribute is defined as the base type.
Alternatively, you can also declare a valid type only on a single field or attribute, rather than declared derived types on the base class. You can attach the XMLELEMENT, XMLATITRIBUTE, or XMLARRAYITEM properties to the field and declare the type of the field or attribute that can be referenced. The XMLSerializer's constructor then adds the code required for serialization and reverse sequence to the serialization class.
Read StackTrace
The Message property of Innerexception is not the only attribute that contains value information. The StackTrace property conveys more details about the false root. At the top of the stack track, you can find the name of the method that first triggered an exception. The method name in the temporary program focuses on the sequence class follow format Write_, follows the format read_ for the deserialization class. In an example with the above error namespace, you can see the method from the abnormal source from Read1_myClass. Later, I will show you how to use the Visual Studio debugger to set breakpoints and single step. However, first let's take a look at the common problems occurring around the anti-sequence of XML documents.
Back to top
Problems occurred during reverse sequence-based XML
The XML Document Decline is an object map is not as easy to make mistakes like the object map sequence as XML. XMLSerializer will be very sensitive when the object does not match the type definition, but if the deserialized XML document does not match the object, it will be very tolerant. The XMLSerizer no longer triggered an exception for the XML elements that do not correspond to the fields or attributes in the reserved object, but only simply trigger events. If you need to track the degree of matching between the anti-sequence of XML documents and the XML format, you can register the handler of these events. However, you do not need to register an event handler to the XMLSerializer to properly handle unmapped XML nodes.
In the reverse selecente process, only a few of the wrong conditions can cause an abnormality. The most common conditions are:
•
The name of the root element or its namespace does not match the desired name.
•
Enumerate data type presents undefined values.
•
The documentation contains illegal XML.
Like serialization, every time there is a problem, the DeserialIze () method will trigger an InvalidOperation exception with the following message.
There is an error in xml document (,).
This exception is usually included in the Innerexception property. The type of inNerexception is different from the actual error that occurs when reading XML documents. If the serialization program cannot be used to pass the type passed to the constructor, the type of document is matched by the type specified by the XMLInClude property or in a more complex heavy load of the XMLSerializer constructor. The innerexception is InvalidCastException. Keep in mind that XMLSerializer will view the qname (ie, the name of the elements) and namespaces to determine which class is to be degraded to the document. They must match the declaration in the .NET class so that XMLSerializer correctly identifies the type corresponding to the root element of the document. Let's take a look at an example:
[Xmlroot (namespace = "urn: my-name")]]]
Public Class Myclass
{
Public String Myfield;
}
Define sequence The following XML documents will result in an exception, because the XML namespace of MyClass elements is not as declared as the XMLRoot attribute on the .NET class, is URN: My-Namespace.
Let us further observe the exception. Abnormal Message is more descriptively than the message captured from the serialize () method; at least it leads to the location of the DeserialIze () in the document. Nonetheless, when you handle large XML documents, view the document and make sure that the error may not be so simple. Innerexception has once again provided better information. This time, it shows:
Hexadecimal Value This problem can be avoided if you are confirmed by the XMLTextReader that sets its Normalization property to True. Unfortunately, ASP.NET Web Services set their normalization attribute to false internally; that is, it will not reach the SOAP message containing these invalid characters. Back to top Abnormality from constructor The last type of problem discussed in this article occurs when the XMLSerializer constructor analyzes the type of incoming. Keep in mind that the constructor will recursively check each public field and attribute in the type hierarchy to create classes for handling serialization and deserialization. It then recompiles these classes instantly, and loads the resulting assembly. Many different problems may occur during this complex process: • The size of the root element is or the type of constructor is not provided by the type of attribute or field reference. • A type in the hierarchy implements a collection interface idictionary. • When performing a type of constructor or attribute accessor in an object map, you need to enhance safety permissions. • The code for the generated serialization cannot be compiled. Trying to transmit to the XMLSerializer constructor can also cause InvalidOperationException, but this exception will not package other exceptions. The Message property contains a full explanation of the reason for the constructor refuses to incoming "type". Attempting to serialize an instance of a class that does not implement a class of constructor without parameters (default constructor), an exception is generated with the following message: Test.nonserializable Cannot Be Serialized Because It Does Not Have A Default Public Constructionor. On the other hand, it is very complicated to solve compilation errors. These issues are exposed to FilenotFoundException with the following 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 not know what is the relationship between "Filling File" and instantiated serialization program objects, but remember: constructor writing C # files and trying to compile these files. The abnormal call stack provides some useful information to provide a basis for this suspicion. This exception occurs when XmlSerializer attempts to load the code generated by the CodeDom called the System.Reflection.Assembly.Load method. This exception does not provide an explanation of the reason why XMLSerializer does not exist according to the speculation of the assembly to be created. Typically, the reason why the assembly does not exist is compilation failed, which is because the serialization attribute generates a code that the C # compile cannot be compiled, but this situation rarely appears. This error occurs when the account or security environment you belong to the XMLSerializer runtime will not access the TEMP directory. Any exception error message triggered by XMLSerializer does not contain actual compilation errors, and even inNNEREXCEPTION does not contain actual compilation errors. This makes it very difficult to solve these anomalies until the Chris Sells released his XMLSerializerPrecompiler tool. XMLSerializerPrecompiler XMLSerializer Precompiler is a command line program that performs the same steps as the XMLSerializer constructor. It analyzes types, generates serialization classes, and compiles these classes - because it is purely designed to troubleshoot tools, so it can safely write any compilation errors to the console. This tool is very convenient to use. You only need to point the tool to the assembly that contains the type that causes exception, and specifies the type to be pre-compiled. Let us look at an example. When you attach the XMLELEMENT or XMLARRAYITEM attribute to fields defined as an interleaving array, a regular report is reported, as shown in the example: Namespace Test { Public Class StringArray { [XMLELEMENT ("ArrayElement", TypeOf (String)] public string [] [] strings; } } When instanting the XMLSerializer object for type Test.StringArray, the XMLSeriRIZER constructor triggers filenotfoundexception. If you compile this class and try to serialize the instance of such a class, you will get FilenotFoundException, but will not get the true clues related to the problem. XMLSerializerPrecompiler provides you with missing information. In my example, the StringArray class is compiled as an assembly called XMLSer.exe, and I must run the tool with the following command line: XMLSerializerPrecompiler.exe Xmlser.exe Test.StringArray The first command line parameter specifies the assembly, and the second parameter defines the class to be pre-compiled. This tool writes a lot of information to the command window. Figure 2. XMLSERIALIZERPRECOMPILER Command Window Output The important code line that needs to be viewed is the code line with compilation errors and two lines similar to the following: XMLSERIALIZER-PRODUCED SOURCE: C: /Docume ~ 1//locals ~ 1/temp/.cs Now, XMLSerializerPrecompiler provides us with compilation errors and a location where you have a source file that cannot be compiled. Debug serialization code Typically, XMLSerializer will delete it when the C # source file that is no longer needed. However, there is an unconfirmed diagnostic switch that can be used to indicate XMLSerializer to keep these files on the hard disk. You can set this switch in the application's .config file: XML Version = "1.0" encoding = "UTF-8"?> If this switch appears in the .config file, the C # source file will remain in the TEMP directory. If your computer is running Windows 2000 or higher, the default location of the Temp directory is / documents and settings // localsettings / temp or / temp (web application running under the ASP.NET account). These C # files are easily lost because their file names look very strange and are randomly generated, such as BDZ6LQ-T.0.cs. XMLSerializerPrecompiler can set this diagnostic switch, so you can open these files in Notepad or Visual Studio to check the code rows that report to compile errors in the XMLSeriRialPrecompiler. You can even perform these temporary serialization classes in one sentence, because the diagnostic switch can keep the .pdb file containing the debug symbol on the hard disk. If you need to set a breakpoint in the serialization class, you can run the application under the Visual Studio debugger. Once you see the relevant message in the output window, indicating that the application has already loaded from the Temp directory, you can open the C # file with the corresponding name, and then set the same as in your own code. point. Figure 3. Compilation error output from diagnostic switch After setting breakpoints in the serialization class, you need to execute the code to call the serialize () or DeserialIze () method on the XMLSerializer object. Note You can only debug serialization and reverse sequence, and cannot debug code generation processes running in the constructor. You can identify each serialization problem by single step in the serialization class. If you want to step on the reverse sequence of SOAP messages, you can use the above skills because the ASP.NET Web service and Web service agent are built on XMLSerializer. You need to do just add the diagnostic switch to your config file and set breakpoints in the class of the deserialized message. If WSDL does not accurately reflect the message format when generating a proxy class, I occasionally use the above techniques to determine the correct serialization property set. Back to top summary These tips should help you diagnose serialization issues in XMLSerializer. Most of you encounter are from the error combination of XML serialization properties, or the XML that does not match the type of type to be retrograde. The serialization attribute control sequence-based code generation, and may result in compilation errors or running. By carefully checking the exception caused by XMLSerializer, you can help you identify the root of the running exception. If you need further diagnostics, you can use the XMLSeriRIzerPrecompiler tool to help you find compilation errors. If any method does not help you find the root source of the problem, you can check the code for automatically created serialization, and execute these code in the debugger.