XML Attributes

I l @ ve RuBoard

So far, we've seen how to return intrinsic types and UDTs from a WebService. The basic serialization provided by WebServices will generally suffice, but there are times when it is necessary to control the representation of elements being returned.

An XML document can have at most one root. An XML root can be defined by making use of the XMLRootAttribute . The XMLRootAttribute is used to specify the following properties in Table 4.4.1.

Table 4.4.1. XMLRootAttribute Instance Properties
Property Meaning
DataType XML data type of the root element
ElementName The name of the root element
Form Qualified or unqualified root element name
IsNullable Determines if the XmlSerializer should serialize if set to null
Namespace Namespace for the root element

A XML root element can contain N number of child elements, and each child is capable of containing N number of child elements. This recursive definition allows for arbitrary nesting depth with the XML document.

Along with a root element, an XML document consists of child elements and attributes. An element can be considered a contained type of entity of the document. The XmlElementAttribute is used to describe these elements. Elements can be a class or members of a class. In addition to specifying XmlElementsAttributes , elements can have attributes applied to them by using the XmlAttributeAttribute class.

So far, only single-level objects have been returned by the WebServices created. The XmlSerializer is quite capable of returning complex XML structures with nested classes. It is also possible to use the various XML attributes in conjunction with structs and to mix in entities with no explicit XML attributes.

To see the power of the XmlSerializer in action, a simple WebService will be created to return an Employee containing two contained objects ”one Address class and one Department struct. Listing 4.4.11 shows the implementation of the Employee , Address , and Department entities.

Listing 4.4.11 Entities.cs
 1: namespace XML  2: {  3:     using System;  4:     using System.Xml;  5:     using System.Xml.Serialization;  6:  7:  8:     [XmlRoot("employee")]  9:     public class Employee 10:     { 11:             private string        m_FirstName; 12:             private string        m_LastName; 13:             private Address        m_Address; 14:             private Department    m_Dept; 15: 16:         //Properties 17:         [XmlAttribute("first_name")] 18:         public string FirstName 19:         { 20:             get{  return m_FirstName; } 21:             set {  m_FirstName = value; } 22:         } 23: 24:         [XmlAttribute("last_name")] 25:         public string LastName 26:         { 27:             get {  return m_LastName; } 28:             set {  m_LastName = value; } 29:         } 30: 31: 32:         [XmlElement("address")] 33:         public Address Address 34:         { 35:             get {  return m_Address; } 36:             set {  m_Address = value; } 37:         } 38: 39:         [XmlElement("department")] 40:         public Department Department 41:         { 42:             get {  return m_Dept; } 43:             set {  m_Dept = value; } 44:         } 45:     } 46: 47: 48:     public class Address 49:     { 50: 51:         //Use Public Fields with XmlAttributes 52:         [XmlAttribute("line1")] 53:         public string Line1; 54: 55:         [XmlAttribute("city")] 56:         public string City; 57: 58:         [XmlAttribute("state")] 59:         public string State; 60: 61:         [XmlAttribute("zip")] 62:         public string Zip; 63:     } 64: 65:     //Use a simple struct 66:     public struct Department 67:     { 68:         //Fields with no XML attributes 69:         public string name; 70:         public int      building_number; 71:     } 72: } 73: 

The entities in Listing 4.4.11 mix and match the various XML attributes and composite class creation. Both Employee and Address make use of the XML attributes, whereas the Department struct utilizes only public fields. By default, all public fields of a class or struct will be serialized by the WebService XML serialization code. This ability to mix and match provides an impressive power that enables you, the developer, to take complete control over the serialization process.

The result of the composite Employee class after serialization can be seen in Figure 4.4.9.

Figure 4.4.9. The XML representation of the Employee class.

graphics/0404fig09.gif

Notice the various XML attributes and how they affect the XML output produced during the serialization of an Employee entity. It is also important to note there is more than one way to decorate a class with XML attributes that achieve the same serialization format. Consider the proxy code generated by the WSDL.exe tool in Listing 4.4.12.

Listing 4.4.12 Client Proxy-Generated Code
 1: // <autogenerated>  2: //     This code was generated by a tool.  3: //     Runtime Version: 1.0.2615.1  4: //  5: //     Changes to this file may cause incorrect behavior and will be lost if  6: //     the code is regenerated.  7: // </autogenerated>  8:  9: // 10: // This source code was auto-generated by wsdl, Version=1.0.2615.1. 11: // 12: using System.Xml.Serialization; 13: using System; 14: using System.Web.Services.Protocols; 15: using System.Web.Services; 16: 17: 18: [ 19: System.Web.Services.WebServiceBindingAttribute( 20:                      Name="Service1Soap", 21:                      Namespace="http://tempuri.org/") 22: ] 23: public class Service1 : System.Web.Services.Protocols.SoapHttpClientProtocol { 24:     public Service1() { 25:         this.Url = "http://localhost/XML/Service1.asmx"; 26:     } 27: 28:     [ 29: System.Web.Services.Protocols.SoapMethodAttribute( 30: "http://tempuri.org/GetEmployee", MessageStyle=System.Web.Services.Protocols. graphics/ccc.gif SoapMessageStyle.ParametersInDocument) 31: ] 32: [return: System.Xml.Serialization.XmlElementAttribute( "employee", IsNullable=false)] 33:     public Employee GetEmployee() { 34:         object[] results = this.Invoke("GetEmployee", new object[0]); 35:         return ((Employee)(results[0])); 36:     } 37: 38:     public System.IAsyncResult BeginGetEmployee( System.AsyncCallback callback, graphics/ccc.gif object asyncState) { 39:         return this.BeginInvoke("GetEmployee", new object[0], callback, asyncState); 40:     } 41: 42:     public Employee EndGetEmployee(System.IAsyncResult asyncResult) { 43:         object[] results = this.EndInvoke(asyncResult); 44:         return ((Employee)(results[0])); 45:     } 46: } 47: 48: public class Employee { 49: 50:     [System.Xml.Serialization.XmlElementAttribute(IsNullable=false)] 51:     public Address address; 52: 53:     [System.Xml.Serialization.XmlElementAttribute(IsNullable=false)] 54:     public Department department; 55: 56:     [System.Xml.Serialization.XmlAttributeAttribute()] 57:     public string first_name; 58: 59:     [System.Xml.Serialization.XmlAttributeAttribute()] 60:     public string last_name; 61: } 62: 63: public class Address { 64: 65:     [System.Xml.Serialization.XmlAttributeAttribute()] 66:     public string line1; 67: 68:     [System.Xml.Serialization.XmlAttributeAttribute()] 69:     public string city; 70: 71:     [System.Xml.Serialization.XmlAttributeAttribute()] 72:     public string state; 73: 74:     [System.Xml.Serialization.XmlAttributeAttribute()] 75:     public string zip; 76: } 77: 78: [ 79: System.Xml.Serialization.XmlTypeAttribute( 80:              Namespace="http://tempuri.org/") 81: ] 82: public class Department { 83: 84:     public string name; 85: 86:     public int building_number; 87: } 88: 

As usual, the WSDL.exe tool produces the necessary proxy code to invoke the requested WebService method. Along with the proxy code, WSDL.exe also produces the Employee , Address , and Department entities as described by the WebServices wsdl document. Notice the differences between the Employee , Address , and Department developed previously and the source generated by the WSDL.exe tool.

Although each class/struct uses a different approach to produce the proper serialization format, both implementations are orthogonal to each other. Basically, only the names have changed on the decorated fields and properties. In effect, the WSDL.exe tool relies on both the various XML attributes and the use of Reflection to produce the proper serialized format.

I l @ ve RuBoard


C# and the .NET Framework. The C++ Perspective
C# and the .NET Framework
ISBN: 067232153X
EAN: 2147483647
Year: 2001
Pages: 204

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net