[ Team LiB ] |
9.1 Defining SerializationSerialization refers to the process of transforming data from an object instance in memory into a structured representation of that data in a stream. Serialization allows you to preserve the state of an application's objects, whether to simply save the data you're working with or to transmit the data to another application. By using the framework to serialize an object to a stream, you can avoid much of the tedium of hand-coding the logic of reading each field from the object and writing its data to the stream. Instead, the serialization class knows how to do this translation with minimal intervention from the programmer. The process of reading a stream of data into a new object instance in memory is deserialization, which is the opposite of serialization. Although you would hope that no data would ever be lost in the serialization-deserialization process, the reality is that different formats support different datatypes, and they do not always map well to each other. .NET takes two different approaches to serialization, runtime serialization and XML serialization. Each has its advantages, and I'll compare them later.
In runtime serialization, the .NET framework uses a formatter class to create a serialized version of an object, using information available about the object from reflection. Reflection is the mechanism by which objects in memory can be interrogated at runtime for information about their fields, properties, methods, and attributes. Different formatters do the actual work of serialization, based on hints the object provides through reflection. In XML serialization, the structured representation is defined via XML syntax. I introduced you to a simple form of serialization in Chapter 8, wherein the XmlSerializer class was used to control the transformation specified by an XML Schema document. XML Schema is one way to specify the serialization format, and I'll talk about .NET's XML serialization functionality in a moment. But first, I'll introduce SOAP. 9.1.1 Introducing the SOAP SpecificationSOAP is one of the underlying technologies behind Web Services. I'll talk more about Web Services in Chapter 10. The development of SOAP began in 1998. The World Wide Web Consortium released a note on SOAP in 2000. .NET explicitly supports section 5 of the SOAP note, which is available on the Web at http://www.w3.org/TR/SOAP/. What SOAP actually provides is a standard mechanism for packaging data for transmission between interoperating computer systems. While other remote procedure call (RPC) protocols exist, most of them were designed before the era of distributed, object-oriented programming. SOAP's design goals include several features not normally found in RPC protocols:
The SOAP specification is made up of three parts:
Although the SOAP specification provides for what is fundamentally a one-way transmission, two-way messaging is possible by sending a SOAP message in response to a SOAP message. Although SOAP is designed to provide messaging regardless of the underlying network protocols, it is typically implemented atop HTTP. A message follows a message path, along which it may reach a number of different applications. Each application that receives the message must take the following steps:
Example 9-1 shows a hypothetical SOAP message that might be used to communicate an order between Angus Hardware and a supplier. I'll use this example throughout the discussion of the SOAP specification. Example 9-1. A SOAP message for a wholesale product order<?xml version ="1.0" encoding="UTF-8" ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Header> <ns1:terms xmlns:ns1="urn:angushardware" SOAP-ENV:MustUnderstand="1">Net 30</ns1:terms> </SOAP-ENV:Header> <SOAP-ENV:Body> <ns1:placeOrder SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <productCode xsi:type="xsd:string">99HGTY</productCode> <quantity xsi:type="xsd:int">300</quantity> </ns1:placeOrder> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
9.1.1.1 The SOAP envelopeThere are four namespaces included in the SOAP message. The first one, with the prefix SOAP-ENV, refers to the SOAP envelope: xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" The SOAP-ENV:Envelope element has two sub-elements, SOAP-ENV:Header and SOAP-ENV:Body. The SOAP-ENV:Header element is optional, and it provides information to the application that processes the message. The element within the SOAP-ENV:Header element can be any element from any namespace other than SOAP-ENV, and it can have any attributes without restriction. Although it is open-ended to allow for maximum flexibility, the SOAP-ENV:Header's sub-elements do have two specific optional attributes, MustUnderstand and Actor. The MustUnderstand attribute has a Boolean value, indicating to the application that if it does not know how to process the message, it must discard the entire message. The Actor attribute, whose value is a URI, can be used when a SOAP message is sent to several applications on a message path, and indicates which application the message is intended for: <SOAP-ENV:Header> <ns1:terms xmlns:ns1="urn:angushardware" SOAP-ENV:MustUnderstand="1">Net 30</ns1:terms> </SOAP-ENV:Header> In Example 9-1, the ns1:terms element indicates the terms Angus Hardware is willing to give their vendor in purchasing more inventory. The terms are Net 30, and the application processing the order must understand the ns1:terms element in order to continue processing. Like SOAP-ENV:Header, the SOAP-ENV:Body element can have any sub-elements. However, unlike SOAP-ENV:Header, SOAP-ENV:Body cannot have any attributes. The content of the SOAP-ENV:Body element is a sequence of actions to be processed; in Example 9-1, the action is a call to the placeOrder method: <SOAP-ENV:Body> <ns1:placeOrder SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <productCode xsi:type="xsd:string">99HGTY</productCode> <quantity xsi:type="xsd:int">300</quantity> </ns1:getInventory> </SOAP-ENV:Body> The ns1:placeOrder element has one attribute, SOAP-ENV:encodingStyle. This attribute indicates the encoding rules for the message, which I'll talk about shortly. A SOAP envelope can also contain a response, as shown in Example 9-2. Example 9-2. A SOAP response message for a wholesale product order<?xml version ="1.0" encoding="UTF-8" ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:placeOrderResponse xmlns:ns1="urn:angushardware" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <ns1:deliveryDate xsi:type="xsd:date">2002-09-04</deliveryDate> </ns1:placeOrderResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Example 9-2 shows a possible response to the message in Example 9-1. In this case, the server responds with a ns1:placeOrderResponse element, containing an ns1:deliveryDate element, which indicates an expected delivery date of September 4, 2002. However, a SOAP response can also include a SOAP-ENV:Fault element, indicating an error. Example 9-3 shows a SOAP fault message. Example 9-3. A SOAP fault message for a wholesale product order<?xml version ="1.0" encoding="UTF-8" ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <SOAP-ENV:Fault> <SOAP-ENV:faultCode xsi:type="xsd:string"> SOAP-ENV:MustUnderstand </SOAP-ENV:faultCode> <SOAP-ENV:faultString xsi:type="xsd:string"> The server did not understand the header element ns1:terms </SOAP-ENV:faultString> <SOAP-ENV:faultActor xsi:type="xsd:string"> Smith's Sprocket Company </SOAP-ENV:faultActor> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope> As you can see, this SOAP message is very similar in overall structure to both the previous examples, except that it includes a SOAP-ENV:Fault element. The SOAP-ENV:faultCode element contains a fault code, which indicates the type of error that occurred. SOAP-ENV:faultString provides a human-readable explanation of the fault; there's also an optional SOAP-ENV:detail element, which could provide more information about the error. Finally, the SOAP-ENV:faultActor indicates which actor had the fault. In this case, the SOAP server at Smith's Sprocket Company has indicated that it does not understand the ns1:terms element in the request header. A few standard SOAP-ENV:faultCode values are defined in the SOAP specification, and they are listed in Table 9-1.
The SOAP-ENV:Header and SOAP-ENV:Fault elements are optional in any SOAP message. The two SOAP messages, request and response, actually have identical structure; the only difference is in which of the two optional elements are included, and in the specific syntax of the body elements. The overall structure of the SOAP message is extremely flexible, which makes it important for the client and server to have well-established rules for the syntax of their communications.
9.1.1.2 Encoding rulesSeveral of the elements in the SOAP messages I just discussed include the SOAP-ENV:encodingStyle attribute: SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" The SOAP-ENV:encodingStyle attribute specifies the encoding system to be used. The encoding system is a mutually agreed-upon way of representing data in a SOAP message. Although the examples use the SOAP 1.1 encoding rules, you may actually use any encoding you wish, or none at all, in your SOAP envelope. To use the SOAP 1.2 encoding system, for example, you would specify http://www.w3.org/2003/05/soap-encoding. The URI, like namespace URIs, is used as a unique name rather than an actual Internet resource. The encoding style applies to the entire scope of the element on which the attribute appears. In Examples 9-1 and 9-2, the SOAP-ENV:encodingStyle attributes appear on the ns1:placeOrder and ns1:placeOrderResponse elements, respectively. 9.1.1.3 RPC representationAlthough the SOAP envelope provides information about the remote method to be called and the encoding of the data being passed to the remote object, it does not inherently contain any information about the remote program or system. SOAP depends on the transport protocol to provide this. While HTTP works very well as a transport, and SOAP has specific bindings for HTTP, there is nothing in the specification that limits your choice of transport protocols. There's not enough room in this book to cover everything about SOAP. For more information, see Programming Web Services with SOAP (O'Reilly). 9.1.2 When to Use SerializationIn general, you should consider using XML serialization when your application requires data to be exchanged between possibly disparate systems, whose only commonality might be the ability to read and write XML. Although this case covers XML serialization in general, it's also important to determine which form of serialization to use. Simple XML serialization is appropriate when you have an existing XML schema (whether a formal W3C XML Schema or simply an agreed-upon format) and wish to read the data into an object; or when you have existing objects and wish to produce a representation of their data in an XML format. These cases usually involve non-interactive data exchange; that is, data is being exchanged, but not in a Web Services context. On the other hand, you should use SOAP serialization when you know that your data exchange partner supports it, or when you are designing a new distributed application that requires interactive data exchange. Finally, you should consider runtime serialization when the communication is happening between two .NET applications. 9.1.3 SOAP Versus XML-RPCRemote procedure calling (RPC) refers to the ability to invoke a method of an object that resides outside of the caller's address space, as if it were local. Although RPC is an old term, dating back to the early days of networked computers, the concept of using XML as an RPC mechanism dates back to the early days of Web Services. SOAP is not the only XML RPC mechanism; in fact, another mechanism, called XML-RPC, is arguably simpler and easier to use. However, this simplicity comes at the expense of flexibility. Although XML-RPC evolved from an early version of SOAP, Microsoft has chosen not to support XML-RPC directly in .NET. However, there is nothing to stop some enterprising developer from producing an XML-RPC framework for .NET.
As I said earlier, .NET supports two general methods of serialization. Which one you should choose depends on your needs. |
[ Team LiB ] |