Passing Complex Data Types

Summary

 

The SOAP Specification and Data Types

The SOAP specification goes into great detail on how to send properly formatted SOAP messages that accommodates just about any data type and any data structure. However, when you inspect the SOAP generated by ASP.NET Web Services you will note that it varies slightly from the SOAP specification by having a simpler format. For example, SOAP accessors, which are variables used to hold the actual values in a message and hence decrease the size of the message are not used by ASP.NET Web Services. Also the type information is not encoded into the actual message, and the data types are not explicitly defined in the SOAP messages itself. Instead the XML Schema Definition (XSD) within the WSDL defines the data types, and the client's proxy converts the data elements in the SOAP message to their appropriate data types as defined by the WSDL. Most of this happens behind the scene.

Because XSD defines data types for Web Services, XSD must be flexible enough to account for every data type found in most languages. And for two different systems to communicate, they must agree on what a particular data type is. The XSD language specification explicitly defines each data type. The following list shows the mapping between CLR (C# and VB.NET) and XSD:

CLR Data Type XSD Data Type
Boolean Boolean
Double Double
Decimal Decimal
Single Float
Int16 Short
Int32 Int
Int64 Long
String String
DateTime TimeInstant

Understanding Classes, XSD, WSDL, and Proxies

It is important to understand the big picture of the relationship of creating complex data types (such as classes and structures) and how their type information is described by WSDL and eventually used when you create a Web Reference. The following figure illustrates this big picture:

The left-hand side represents a Web Service whose methods instantiate several complex types, and the right-hand side represents a client that accepts/sends complex types from/to the Web Service. During development of the Web Form, when the developer adds a Web Reference to the target Web Service, a series of .NET Framework classes on the server begin to perform the process of reflection on the data types and structures used in the target Web Service and translate that information into a serialized XML format called XML Schema Definition, XSD. .NET uses the reflection process to inspect and discover the methods, properties, and data types used in a given class. The XSD is then embedded into the WSDL file in the Types section of that document. When using VisualStudio.NET, these XSD/Reflection classes are used behind the scenes to convert classes to XSD and convert XSD back to classes.

After the WSDL file for the Web Service is created and completed (with XSD for all the data types and structures defined in the file), the WSDL is sent to the Web Service consumer. The consumer's VisualStudio.NET processes the WSDL file and constructs classes (called a proxy) that the developer can use to code with, as though the Web Service code were in the same project that the developer is working on.

Passing .NET Structures over Web Service

The example in this section illustrates how to send objects via Web Services. The Web Service will use the following three classes:

Once the Web Service has been built, you can examine the WSDL file to view how XSD describes the classes/types used by the Web Service. And when a Web Reference is added to this Web Service in the client application, the .NET Framework will interpret the XSD and create classes that represents the same exact structure of the classes in the Web Service (CustomerInfo, OrderInfo, Part). The .NET Framework will even create the relationship between OrderInfo and Part correctly and allow you to use these objects without worrying that they came from the Web Service.

Project Passing Classes illustrates how to pass classes and arrays using Web Services. The following is output from the project:

Passing XML With Web Services

You can send entire XML documents or nodes via Web Services. Why would you want to do this? You may need to allow your consumers to pass unknown or undefined XML structures to the Web Service, and then perform some parsing on that document (via XSLT, XPATH, etc.). Passing XML to Web Services then becomes a variant of Web Services enabling consumers to send individual classes, nodes or whatever they want to Web Services.

Assume you had a Web Method that returned an XML node back to its consumer. If you look at the WSDL file for the definition of that node, you will note that XSD used the element <any>.  This means that the Web Service will literally accept anything you pass it. Making Web Services accept anything you pass them is considered bad form because you would be circumventing the entire purpose of WSDL - to allow a client-side proxy to be created that is strongly typed and early bound to the Web Service's data. Therefore, it is recommended that clients/consumers fully test code and validate values before sending them over to the Web Service, and to dutifully handle exceptions returned from the Web Service. Therefore, you have to judge yourself how "idiot proof" you want to make your Web Service.