Message Design in a Service Contract

Retired Content

The Web Service Software Factory is now maintained by the community and can be found on the Service Factory site.

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies.
This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Retired: November 2011

There are two approaches to message design for services built using the .NET Framework, implicit and explicit. The implicit approach uses a parameter programming model, and the explicit approach defines a message contract programming model.

Implicit Message Design: Parameter Programming Model

The implicit approach to the message design process is similar to the way methods have traditionally been developed using distributed object technologies. In this case, messages are not designed by the developer at all. Instead, the service contract is implicitly defined by the types of the method's parameters. The following code is an example of implicit message design using ASMX.

[WebService(Namespace = "http://GlobalBank/CustomerManager/2006/06")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class CustomerManager : System.Web.Services.WebService 
{
    [WebMethod]
public float GetCustomerCreditInformation(string CustomerId, int Year) {
        // Logic to retrieve customer credit information by Id constrained by Year 
    }
}

The following SOAP message represents the resulting message produced from the previous code sample.

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetCustomerCreditInformation xmlns="http://GlobalBank/CustomerManager/2006/06">
      <CustomerId>DMS4408</CustomerId>
      <Year>1970</Year>
    </GetCustomerCreditInformation>
  </soap:Body>
</soap:Envelope>

Explicit Message Design: Message Contract Design Programming Model

The explicit approach to the message design process encapsulates data into document-based XML messages using types explicitly defined for this purpose. Using explicit messages is the recommended practice when a common information model is used within an organization. This provides a common, interoperable semantic definition for all messages exchanged by the services. The following code example shows a service interface designed using a message contract that is composed of two data contracts. These data contracts are specified inline, but they could have also been included from a standard library of data contracts.

[DataContract]
public class Entity
{
   [DataMember]
   public string name;
   [DataMember]
   public int age;
   [DataMember]
   public Address address;
}

[DataContract]
public class Address
{
   [DataMember]
   public string AddressLine1;
   [DataMember]
   public string AddressLine2;
   [DataMember]
   public string City;
   [DataMember]
   public string State;
   [DataMember]
   public string PostCode;
   [DataMember]
   public string Country;
}

[MessageContract]
public class CustomerNotificationMessage 
{
   [MessageHeader]
   public string Priority;
   [MessageBodyMember]
   public Entity customer;
   [MessageBodyMember]
   public Entity courier;
}

[ServiceContract]
public interface IOrderManager
{
   [OperationContract IsOneWay="True"]
   public void SendDeliveryNotification(CustomerNotificationMessage customerNotificationMessage);
}

Using the Message Contract Programming Model

The .NET Framework and the Service Factory support two techniques for message contract design. One technique starts with XML Schema definition language (XSD); the other technique starts with XML serializable types.

Message Design Using XML Schema (XSD)

A common challenge that developers face when integrating applications that run on different platforms is how to translate primitive data types from one platform to another. Different programming languages and operating systems support different data types, each with different names and characteristics. For example, an integer in Visual Basic 6.0 is 16 bits, while an integer in Visual Basic .NET or Visual C# is 32 bits. Similarly, if you expose a float data type from Java, it is not clear what the corresponding data type should be in the .NET Framework.

If you combine different data types into complex structures, making use of collection classes, arrays, and platform-specific data types, such as datasets, you are more likely to encounter translation problems between platforms. Even the treatment of NULL values can vary across platforms.

XML Schema defines a common primitive type system. As a result, when messages are designed using XML Schema (XSD), and platform-specific data types are generated from the XML schema (XSD), some interoperability concerns between platforms can be resolved.

There are a number of tools you can use to automatically generate .NET Framework data types from XML Schema (XSD), and schema from .NET Framework data types in the .NET Framework. These include the following:

  • Xsd.exe. This tool ships with the .NET Framework 2.0. If you run the Xsd.exe utility against an XML schema (.xsd) file with the /c switch, you can automatically generate the appropriate classes. Similarly, you can run the Xsd.exe utility against a .NET Framework assembly to generate XML schema (.xsd) files.
  • SvcUtil. This tool ships with the .NET Framework 3.x. You can run SvcUtil /dconly for XML Schemas (XSD) that conform to the subset of XML Schema (XSD) that data contracts support. For schemas that do not conform to the subset of schema that data contracts support, you should use Xsd.exe /c to specify that your services use the XmlSerializer, by using the [XmlSerializerFormat] attribute on the service contract.

Note

For more details about data contracts, see the “DataContractSerializer” topic below.

Key challenges to be aware of when adopting this approach include the following:

  • There may be a mismatch between language type systems and the XML Schema (XSD) specification. For example, the xs:Choice element does not have a natural implementation in standard type systems.
  • There may be inconsistent implementations of schema types across platforms. For example, inconsistent mapping of XML Schema (XSD) data types, such as dates; inconsistent treatment of arrays and bare arrays; and treatment of null values.
  • Different vendors may also implement different subsets of XML Schema (XSD).

Message Design Using Serializable Types

XML serialization is the process of converting members of an object into XML for communication between a sender and a receiver. Deserialization is the reverse process—it assigns the XML to an equivalent object for the receiver.

You can use two different approaches to create serializable types:

  • XmlSerializer. This type is supported by .NET Framework 2.0 and .NET Framework 3.x.
  • DataContractSerializer. This type is supported only by .NET Framework 3.x.

The next sections describe both serializers in more detail.

XmlSerializer

The XmlSerializer can be used by services designed using ASMX (.NET Framework 2.0) and WCF (.NET Framework 3.x). The XmlSerializer allows your data types to be defined using programming language constructs, such as properties and fields. By default, the XmlSerializer serializes all properties and fields marked as public, unless the XmlIgnoreAttribute is specified.

You can gain full control of the XML serialization process by using a comprehensive set of attributes such as XmlElement or XmlAttribute. You have the option of creating your own classes, annotated with attributes, or using the XML Schema Definition Tool (Xsd.exe) to generate the classes based on an existing XML Schema definition (XSD). If you have an XML Schema (XSD), you can run Xsd.exe to produce a set of classes that are strongly typed to the schema and annotated with attributes to adhere to the schema when serialized.

Note

For custom types, it is also possible to control the serialization process of the XmlSerializer by deriving classes from IXmlSerializable.

Characteristics of using XML serializable types and the XmlSerializer include the following:

  • XML serializable types provide a programmatic alternative to using the XML Schema (XSD). Using these, developers can manipulate the way in which a .NET Framework object is serialized using the XML serialization attributes, such as XmlElementAttribute, XmlAttributeAttribute, and XmlIgnoreAttribute.
  • XML serializable types can represent many XML schema types. These,.NET Framework XML serializable types can be used programmatically. However, these types do not support complete coverage of XML Schema (XSD).

You should be aware of the following considerations when using XML serializable types and the XmlSerializer:

  • Modifying the XML serialization process using XML serialization attributes is often unnecessary and may result in unplanned interoperability issues or types that do not conform to schemas as expected.
  • All public properties and fields will be serialized, unless the XmlIgnore element is used or the members are read-only or write-only.
  • Some .NET Framework classes do not support serialization using the XmlSerializer. For example, classes that implement the IDictionary interface, such as hash tables, cannot be serialized.
  • All members must be public to be serialized.

The ASMX guidance package encourages developers to write ASMX Web services using the .NET Framework 2.0 to create reusable .NET Framework data types. This simplifies the migration of the data types to data contracts when adopting WCF. Although no formal message contract exists in the .NET Framework 2.0, the guidance package also incorporates a similar concept to the WCF message contract for composing messages out of data types. The resulting messages are named message types.

Message types provide a mechanism for composing messages out of several .NET Framework data types when there is no reason to formalize the relationship between data types into another data type. The preceding code snippet—though based on WCF instead of ASMX—includes a message that contains information about a customer and a courier, which is something that may not occur often enough to warrant formalizing it as a data type to be frequently reused. However, the entity type includes customer information and a reference to an address because these combinations are likely to be frequently reused.

DataContractSerializer

The .NET Framework 3.x includes formal support for specifying a service contract. This includes specification of the service interface; it also includes specification of data and messages within the contract.

The DataContractSerializer supports serialization of messages that are created using data contracts and message contracts. It is the default serializer for Web services built using the .NET Framework 3.x.

Note

To create an XML schema from an application that has been defined using data contracts, you should use the Service Model Metadata Utility Tool (Svcutil.exe) with the /dconly command line option. When the input to the tool is an assembly, by default, the tool generates a set of XML Schemas (XSD) that defines all the data contract types found in that assembly.

The following list includes benefits of programmatically specifying service interfaces using the DataContract semantics and the DataContractSerializer:

  • Using the DataContract semantics and the DataContractSerializer provides a simpler programming model that enforces the specification of data to be serialized as an explicit activity. This specification conforms to the Service-Oriented Architecture tenet of defining explicit boundaries. Only members specified as being a DataMember are serialized. Similarly, .NET Framework classes are viewed as internal to the service allowing the DataContractSerializer to serialize members marked as internal or private.
  • The DataContractSerializer is designed to use a well-known subset of XML Schema (XSD), which increases the probability of a service being interoperable. DataContract types can be designed in the .NET Framework and then exported to XML Schema (XSD) using SvcUtil /dconly where XML Schemas are required such as in an enterprise information model. In this case, the schemas generated are very likely to be interoperable.
  • The DataContractSerializer can serialize .NET Framework types that include extensive support for collections. For example, types that derive from IDictionary, such as hash tables and [Serializable] types, are supported.
  • The developer is only responsible for specifying the data contract namespaces and element names; the developer is not involved in any other aspect of the serialization process.
  • The DataContractSerializer is optimized for performance, which decreases the cost of serialization over the XmlSerializer.

You should be aware of the following issues when using data contracts and the DataContractSerializer:

  • Data contracts are not intended to support all schema constructs. In many cases, you cannot represent existing schemas using data contracts. This is because many existing schemas use features such as XML attributes, which are not implemented by data contracts.
  • The DataContractSerializer provides very little control over the resulting XML. If you need fine-grained control over the way a message is serialized, you should probably use the XmlSerializer instead.
  • Messages might be larger than messages that are serialized using the XmlSerializer. This is because of the use of XML elements for serializing instances of types within messages.

More Information