Microsoft KB Archive/325691

From BetaArchive Wiki

Article ID: 325691

Article Last Modified on 5/9/2007



APPLIES TO

  • Microsoft .NET Framework 1.0



This article was previously published under Q325691

SYMPTOMS

System.Xml.XmlSerializer does not serialize default values that are present in the XML schemas (XSD). For example, if the schema contains the following line, the default value of False for the <boolf> element is not serialized:

<xsd:element name="boolF" type="xsd:boolean" minOccurs="1" maxOccurs="1" default="false" />
                

CAUSE

The following is an excerpt from the Microsoft .NET Framework SDK documentation:

If the value assigned to a field or property is equal to the default value for that field or property, the XmlSerializer will not serialize the value to the XML-instance.


For more information about this behavior, see the following Microsoft Developer Network (MSDN) Web site:

RESOLUTION

One of following two workarounds can be used to resolve this problem:

  1. After the Xsd.exe file generates the classes from the schemas, manually comment out or remove all of the [System.ComponentModel.DefaultValueAttribute("myFieldName")] attributes from the class files.
  2. Use the class constructors instead of the schema to assign the default values.


STATUS

This behavior is by design.

Microsoft plans to change this behavior in the next major version release of the .NET Framework.

MORE INFORMATION

This behavior introduces limitations such as the following:

  • The structure (the schema or the class) must always be passed with the data.
  • To recover the default value from the schema, it must be parsed each time.

Steps to Reproduce the Behavior

  1. Use a text editor such as Notepad to save the following as Q325691.xsd:

    <?xml version="1.0" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  targetNamespace="urn:myNS" xmlns:myXMLNS="urn:myNS" elementFormDefault="qualified">
    
    <xsd:element name="testDefault" type="myXMLNS:TestDefault"/>
    <xsd:complexType name="TestDefault">
        <xsd:sequence>
            <xsd:element name="str" type="xsd:string" maxOccurs="1" />
            <xsd:element name="strDefault" type="xsd:string" minOccurs="1" maxOccurs="1" default="Default Value" />
            <xsd:element name="boolT" type="xsd:boolean" minOccurs="1" maxOccurs="1" default="true" />
            <xsd:element name="boolF" type="xsd:boolean" minOccurs="1" maxOccurs="1" default="false" />
            <xsd:element name="decimalval" type="xsd:decimal" minOccurs="1" maxOccurs="1" default="10" />
        </xsd:sequence>
    </xsd:complexType>
    </xsd:schema>
  2. Use the Xsd.exe utility to create a Microsoft .NET class for this schema. To do this, click Start, click Programs, click Microsoft Visual Studio .NET, click Visual Studio .NET Tools, and then click Visual Studio .NET Command Prompt to open the Visual Studio .NET command window, and then run a command similar to the following:

    xsd.exe /c /n:TestDefaultNS C:\myDir\Q325691.xsd /out:C:\myDir

    The /c switch indicates class creation, the /out switch indicates the output directory, and the /n switch specifies the namespace to use when generating the class. The output will look similar to the following:

    Microsoft (R) Xml Schemas/DataTypes support utility
    [Microsoft (R) .NET Framework, Version 1.0.3705.0]
    Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.
    
    Writing file 'C:\myDir\Q325691.cs'.
                        

    This creates a Visual C# class named Q325691.cs. Its content looks like the following:

    //------------------------------------------------------------------------------
    // <autogenerated>
    //     This code was generated by a tool.
    //     Runtime Version: 1.0.3705.0
    // 
    //     Changes to this file may cause incorrect behavior and will be lost if 
    //     the code is regenerated.
    // </autogenerated>
    //------------------------------------------------------------------------------
    
    // 
    // This source code was auto-generated by xsd, Version=1.0.3705.0.
    // 
    namespace TestDefaultNS {
        using System.Xml.Serialization;
        
        
        /// <remarks/>
        [System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:myNS")]
        [System.Xml.Serialization.XmlRootAttribute("testDefault", Namespace="urn:myNS", IsNullable=false)]
        public class TestDefault {
            
            /// <remarks/>
            public string str;
            
            /// <remarks/>
            [System.ComponentModel.DefaultValueAttribute("Default Value")]
            public string strDefault = "Default Value";
            
            /// <remarks/>
            [System.ComponentModel.DefaultValueAttribute(true)]
            public bool boolT = true;
            
            /// <remarks/>
            [System.ComponentModel.DefaultValueAttribute(false)]
            public bool boolF = false;
            
            /// <remarks/>
            [System.ComponentModel.DefaultValueAttribute(typeof(System.Decimal), "10")]
            public System.Decimal decimalval = ((System.Decimal)(10m));
        }
    
    }
  3. Create a new Microsoft Visual C# .NET console application named Q325691, and then paste the following in the Class1.cs file:

    using System;
    using System.IO;
    using System.Text;
    using System.Xml.Serialization;
    using TestDefaultNS;
    
    namespace Q325691
    {
       class Class1
       {
          [STAThread]
          static void Main(string[] args)
          {
             try
             {
                // Create a new class instance for serialization.
                TestDefault td = new TestDefault();
                XmlSerializer serializer = new XmlSerializer(typeof(TestDefault), "urn:myNS");
                      
                // Serialize the object and display the output.
                StringBuilder sb = new StringBuilder();
                StringWriter sw = new StringWriter(sb);
                serializer.Serialize(sw, td);
                Console.Write(sw.ToString() + "\n\n");
             }
             catch (Exception ex)
             {
                Console.Write(ex.Message + "\r\n" + ex.InnerException.Message);
             }
          }
       }
    
    }
  4. On the Project menu, click Add Existing Item to add the Q325691.cs class file to the project.
  5. Compile and run the application. The output will look similar to the following. Note that the elements are not serialized:

    <?xml version="1.0" encoding="utf-16"?>
    <testDefault xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                      xmlns="urn:myNS" />
                        
  6. Modify Q325691.cs to try the first workaround, as follows. Note that the lines that specify DefaultValueAttribute are commented out:

    //------------------------------------------------------------------------------
    // <autogenerated>
    //     This code was generated by a tool.
    //     Runtime Version: 1.0.3705.0
    // 
    //     Changes to this file may cause incorrect behavior and will be lost if 
    //     the code is regenerated.
    // </autogenerated>
    //------------------------------------------------------------------------------
    
    // 
    // This source code was auto-generated by xsd, Version=1.0.3705.0.
    // 
    namespace TestDefaultNS {
        using System.Xml.Serialization;
        
        
        /// <remarks/>
        [System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:myNS")]
        [System.Xml.Serialization.XmlRootAttribute("testDefault", Namespace="urn:myNS", IsNullable=false)]
        public class TestDefault {
            
            /// <remarks/>
            public string str;
            
            /// <remarks/>
            //[System.ComponentModel.DefaultValueAttribute("Default Value")]
            public string strDefault = "Default Value";
            
            /// <remarks/>
            //[System.ComponentModel.DefaultValueAttribute(true)]
            public bool boolT = true;
            
            /// <remarks/>
            //[System.ComponentModel.DefaultValueAttribute(false)]
            public bool boolF = false;
            
            /// <remarks/>
            //[System.ComponentModel.DefaultValueAttribute(typeof(System.Decimal), "10")]
            public System.Decimal decimalval = ((System.Decimal)(10m));
        }
    }
                        
  7. Compile and run the application. The output will look similar to the following. Note that the elements are serialized:

    <?xml version="1.0" encoding="utf-16"?>
    <testDefault xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                      xmlns="urn:myNS">
      <strDefault>Default Value</strDefault>
      <boolT>true</boolT>
      <boolF>false</boolF>
      <decimalval>10</decimalval>
    </testDefault>
                        


REFERENCES

For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

314150 INFO: Roadmap for XML Serialization in the .NET Framework


For more information, visit the following Microsoft Developer Network (MSDN) Web site:

Keywords: kbprb KB325691