[ Team LiB ] Previous Section Next Section

9.4 SOAP Serialization

There's another form of XML serialization, which may seem redundant at first. You'll recall that runtime serialization was able to encode an object using SOAP. The SoapFormatter produced a SOAP stream that was optimized for recreating the original object in another .NET application; specifically, the object and all its members were encoded using CLR types. A non-.NET application reading that SOAP stream would most likely have no idea what to do with the data.

However, the XmlSerializer can also serialize an object to SOAP, with an emphasis on the standard SOAP encodings. With SOAP serialization, you get all the interoperability of XML, with additional CLR awareness. The key to standards-compliant SOAP serialization is the SoapReflectionImporter class.

The .NET Framework SDK Documentation will tell you that SoapReflectionImporter is reserved for internal use, and should not be used by your application. However, it does have one constructor and one method that you can use to serialize objects to SOAP.

The code in Example 9-9 demonstrates how to serialize the personnel records from earlier examples to SOAP, using the same Personnel class and the CreatePersonnel( ) method from before.

Example 9-9. Serializing personnel records to SOAP
public static void Main(string [ ] args) {

  Personnel personnel = CreatePersonnel( );
    
  SoapReflectionImporter importer = new SoapReflectionImporter( );
  XmlTypeMapping mapping = importer.ImportTypeMapping(typeof(Personnel));
  XmlSerializer serializer = new XmlSerializer(mapping);
    
  using (StreamWriter stream = File.CreateText("PersonnelSoap2.xml")) {
    XmlTextWriter writer = new XmlTextWriter(stream);
    writer.Formatting = Formatting.Indented;
    writer.WriteStartElement("AngusHardware");
    serializer.Serialize(writer,personnel);
    writer.WriteEndElement( );
  }
}

The object will be serialized to the XML shown below:

<AngusHardware>
  <Personnel xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/
2001/XMLSchema-instance" id="id1">
    <Employees href="#id2" />
  </Personnel>
  <q1:Array id="id2" q1:arrayType="Employee[1]" xmlns:q1="http://schemas.xmlsoap.org/
soap/encoding/">
    <Item href="#id3" />
  </q1:Array>
  <Employee id="id3" d2p1:type="Employee" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-
instance">
    <FirstName xmlns:q2="http://www.w3.org/2001/XMLSchema" d2p1:type="q2:string">
Niel</FirstName>
    <MiddleInitial xmlns:q3="http://www.w3.org/2001/XMLSchema" d2p1:type="q3:string"
>M</MiddleInitial>
    <LastName xmlns:q4="http://www.w3.org/2001/XMLSchema" d2p1:type="q4:string"
>Bornstein</LastName>
    <Addresses href="#id4" />
    <HireDate xmlns:q5="http://www.w3.org/2001/XMLSchema" d2p1:type="q5:dateTime">
2001-01-01T00:00:00.0000000-05:00</HireDate>
  </Employee>
  <q6:Array id="id4" q6:arrayType="Address[1]" xmlns:q6="http://schemas.xmlsoap.org/
soap/encoding/">
    <Item href="#id5" />
  </q6:Array>
  <Address id="id5" d2p1:type="Address" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-
instance">
    <AddressType d2p1:type="AddressType">Home</AddressType>
    <Street href="#id6" />
    <City xmlns:q7="http://www.w3.org/2001/XMLSchema" d2p1:type="q7:string"
>Atlanta</City>
    <State d2p1:type="State">GA</State>
    <Zip xmlns:q8="http://www.w3.org/2001/XMLSchema" d2p1:type="q8:string">30037
</Zip>
  </Address>
  <q9:Array id="id6" xmlns:q10="http://www.w3.org/2001/XMLSchema" q9:arrayType="q10:
string[1]" xmlns:q9="http://schemas.xmlsoap.org/soap/encoding/">
    <Item>999 Wilford Trace</Item>
  </q9:Array>
</AngusHardware>

That's not very pretty. Fortunately, just as there are attributes that affect the serialization of an object to XML, there are attributes that affect the serialization of an object to SOAP. Table 9-3 lists them, with their descriptions.

Table 9-3. Attributes that affect SOAP serialization

Attribute name

Description

SoapAttributeAttribute

Place this attribute on a member to indicate that it is to be serialized as a SOAP attribute.

SoapElementAttribute

Place this attribute on a member to indicate that it is to be serialized as a SOAP element.

SoapEnumAttribute

Place this attribute on a member that returns an enumeration type to indicate how it is to be serialized to SOAP.

SoapIgnoreAttribute

Place this attribute on a member to indicate that it is not to be serialized to SOAP.

SoapIncludeAttribute

Place this attribute on a member to have XmlSerializer recognize base and derived classes.

SoapTypeAttribute

Place this attribute on a class to indicate that the class is to be included in the generated XML Schema definition.

Just as with XML attributes, you can override the SOAP attributes that affect serialization at runtime. To make the Personnel object serialize a little more sensibly, you can either add the attributes to the Personnel type's source code, or you can add them using the SoapAttributeOverrides class.

The use of SoapAttributeOverrides is similar to XmlAttributeOverrides. Rather than go into extreme detail, I'll just show you the code, again with the changes highlighted:

Personnel personnel = CreatePersonnel( );

SoapAttributeOverrides overrides = new SoapAttributeOverrides( );
SoapAttributes attributes = new SoapAttributes( );
attributes.SoapElement = new SoapElementAttribute("employees");
overrides.Add(typeof(Personnel), "Employees",  attributes);

SoapReflectionImporter importer = new SoapReflectionImporter(overrides);
XmlTypeMapping mapping = importer.ImportTypeMapping(typeof(Personnel));
XmlSerializer serializer = new XmlSerializer(mapping);

using (StreamWriter stream = File.CreateText("PersonnelSoap2.xml")) {
  XmlTextWriter writer = new XmlTextWriter(stream);
  writer.Formatting = Formatting.Indented;
  writer.WriteStartElement("AngusHardware");
  serializer.Serialize(writer,personnel);
  writer.WriteEndElement( );
}

The only changes effected by the SoapAttributeOverrides in this example is to change the name of the Employees element to employees, as shown here:

<AngusHardware>
  <Personnel xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/
2001/XMLSchema-instance" id="id1">
    <employees href="#id2" />
  </Personnel>
  ...
</AngusHardware>
    [ Team LiB ] Previous Section Next Section