SOAP, .NET, and COM an Introduction - Part III

SOAP Classes in .NET

.NET provides a complex however well-designed system that you can use to implement Web Services. From a programming model perspective, a Web Service in .NET is little more than a method in a class. You simply hit on a couple attributes, than you will have a Web Service. Moreover, that is a good obsession, which we want that. However, it is also nice to look under the hood to see what is running this mechanism.

The .NET SoapFormatter Class

SoapFormatter is one efficient .NET SOAP class. Its purpose in life is to format a generic .NET object using a SOAP format, given a stream. The class itself has several methods, but the two most interesting are Serialize () and Deserialize (). Serialize () takes as input both a stream into which the SOAP output will be formatted and an object to format. Deserialize () takes the stream from which an object will be created.

To demonstrate SOAP formatting in .NET, Listing 4.2 provides you with a short C# console application that formats the jagged array example into a SOAP format, saves it to disk, and deserializes the array.

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
namespace SoapSerializer
{
/// <summary>
/// Summary description for SoapSerializerTester.
/// </summary>
class SoapSerializerTester
{
bool Serialize(string strPath, Object objStuff)
{
bool bReturn = true;
try
{
// Create a file stream
FileStream fstmOutput = new FileStream(strPath,
FileMode.Create);
// Create the formatter we'll associate
// with this stream
SoapFormatter sfmtFormatter = new SoapFormatter();
// Serialize and save the object
sfmtFormatter.Serialize(fstmOutput,objStuff);
// Close the file stream
fstmOutput.Close();
}
//try
catch(Exception e)
{
Console.WriteLine("{0}",e.Message);
bReturn =
false;
}
// catch
return bReturn;
}
bject Deserialize(
string strPath)
{
Object objReturn =
null;
try
{
// Create a file stream
FileStream fstmInput = new FileStream(strPath,
FileMode.Open);
// Create the formatter we'll associate
// with this stream
SoapFormatter sfmtFormatter = new SoapFormatter();
// Deserialize and return the object
objReturn = sfmtFormatter.Deserialize(fstmInput);
// Close the file stream
fstmInput.Close();
}
//try
catch(Exception e)
{
Console.WriteLine("{0}",e.Message);
objReturn =
null;
}
// catch
return objReturn;
}
static void Main(string[] args)
{
try
{
// Create an instance...
SoapSerializerTester sst1 =
new SoapSerializerTester();
// Create a rough array to serialize and
// deserialize
int[][] q = {new int[2], new int[4], new int[3]};
q[0][0] = 4;
q[0][1] = 7;
q[1][0] = 15;
q[1][1] = 72;
q[1][2] = 6;
q[1][3] = 167;
q[2][0] = 1;
q[2][1] = 90;
q[2][2] = 659;
// Serialize the jagged array
if ( !sst1.Serialize("c:\\printed.txt",(Object)q) )
{
Console.WriteLine("Failed to serialize object...");
return;
}
// if
int[][] r = (int[][])sst1.Deserialize("c:\\printed.txt");
if ( (Object)r == null )
{
Console.WriteLine("Failed to deserialize object...");
return;
}
// if
// Write results...
Console.WriteLine("Result was {0}",r.ToString());
Console.WriteLine(" [0][0] = {0}",r[0][0]);
Console.WriteLine(" [0][1] = {0}",r[0][1]);
Console.WriteLine(" [1][0] = {0}",r[1][0]);
Console.WriteLine(" [1][1] = {0}",r[1][1]);
Console.WriteLine(" [1][2] = {0}",r[1][2]);
Console.WriteLine(" [1][3] = {0}",r[1][3]);
Console.WriteLine(" [2][0] = {0}",r[2][0]);
Console.WriteLine(" [2][1] = {0}",r[2][1]);
Console.WriteLine(" [2][2] = {0}",r[2][2]);
Console.ReadLine();
}
// try
catch (Exception e)
{
Console.WriteLine("{0}",e.Message);
}
// catch
}
}
}

If you run this code and open printed.txt, you will find the SOAP output shown in following Listing.

<SOAP-ENV:Envelope
xmlns
:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/
xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/
SOAP-ENV:encodingStyle=http://schemas.xmlsoap.org/soap/encoding/
xmlns:a1="http://schemas.microsoft.com/clr/ns/System">
<
SOAP-ENV:Body>
<
SOAP-ENC:Array SOAP-ENC:arrayType="a1:Int32[][3]">
<
item href="#ref-2"/>
<
item href="#ref-3"/>
<
item href="#ref-4"/>
</
SOAP-ENC:Array>
<
SOAP-ENC:Array id="ref-2" SOAP-ENC:arrayType="xsd:int[2]">
<
item>4</item>
<
item>7</item>
</
SOAP-ENC:Array>
<
SOAP-ENC:Array id="ref-3" SOAP-ENC:arrayType="xsd:int[4]">
<
item>15</item>
<
item>72</item>
<
item>6</item>
<
item>167</item>
</
SOAP-ENC:Array>
<
SOAP-ENC:Array id="ref-4" SOAP-ENC:arrayType="xsd:int[3]">
<
item>1</item>
<
item>90</item>
<
item>659</item>
</
SOAP-ENC:Array>
</
SOAP-ENV:Body>
</
SOAP-ENV:Envelope>

The output is very loyal to the SOAP specification! For the reason that of .NET serializing .NET datatypes, the array is of type Int32 rather than int. You might have to adjust the SOAP packet as it leaves your local machine if the remote Web Service cannot handle Int32 datatypes (or cannot map them to 32-bit integers).

.NET SOAP Framing Classes

The entire .NET SOAP packet framing classes will not be discussed in detail here. In the later articles, as you create Web Services and play with the SOAP formatting without having to drop into raw XML to make changes, you will see a lot of code that uses those classes.

These classes support the frame, or the layout, of the SOAP packet, therefore they are called framing classes in contrast to the actual serialization classes that manage the serialization and formatting of data that is to be placed into the SOAP packet (SoapFormatter being one such class).

SOAP Encoding

Two different encoding styles are defined by the WSDL SOAP extensibility elements; Document and RPC. The Document style of encoding is intended to help document-oriented messages that will be exchanged between the client and the server. The encoding style affects the format in which the Web service expects SOAP requests to be encoded by the client and how the response received from the Web service will be encoded. As an easy way to facilitate procedure-based communication between the client and the server, ASP.NET Web services have extremely been showcased. However, Document is the default encoding style.
As you may recall, the default encoding style is set in the WSDL document using the style attribute of the binding extensibility element. By decorating the class with the SoapDocumentService or SoapRpcService element, you can set the default encoding style value. Since the InstantQuote Web method is intended to support procedure-oriented communication between the client and the server, the following example uses the SoapRpcService attribute to set the style to RPC:

using System;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace StockManageFirm
{
[WebService(Description="This Web service provides services related to
securities.")]
[SoapRpcService]
public class Securities : WebService
{
[WebMethod(Description="Used to obtain a real- time quote for a given security.")]

public
double InstantQuote(string symbol)
{
double price = 0;
// Implementation...
return price;
}
}
}
Including InstantQuote, all methods that Securities class defines, will default to RPC-style encoding. This default can be overridden by decorating a method with the SoapDocumentMethod attribute. On the other hand, if you want to state Document as the default, you can use the SoapDocumentService attribute.

The SoapDocumentService attribute exposes three properties that you can set to control how the SOAP documents are formatted. Among these three properties, the SoapRpcService attribute supports only the RoutingStyle property.

With the SOAP extension elements, you can also specify whether the individual messages within an operation are literal or encoded. If it is literal, the message must be formatted exactly as dictated by the schema. If it is encoded, the message can be encoded as specified. For RPC-style documents, the use attribute is always set to Encoded.

The means of specifying a default for the use attribute are not provided by the WSDL SOAP extension elements. Expediently, via the Use property, the SoapDocumentService attribute does so. The ASP.NET runtime will spread the value of this property to every WSDL message definition. The Use property can be set to one of three values defined in the SoapBindingUse enumeration: Literal, Encoded, or Default. The default is Literal.

The value of the use attribute for RPC-style documents is encoded. The SoapRpcService attribute does not expose a Use property, so the value cannot be changed.

By setting the RoutingStyle parameter of the SoapDocumentService or SoapRpcService attribute you can indicate whether the SOAPAction header should be populated. The RoutingStyle parameter is of type SoapServiceRoutingStyle and it can be set to SoapAction or RequestElement. The default is SoapAction.
The SoapDocumentService attribute can also be used to indicate how parameters should be encoded within the body of the message. You can set the ParameterStyle property to be one of three values defined in the SoapParameterStyle enumeration: Bare, Wrapped, or Default.

Wrapped means that the parameters will be wrapped within a parent element. The parent element will have the same name as the Web method. Bare means that the parameter elements will appear as direct children of the SOAP body element. The default is Wrapped. Because RPC-style documents follow the encoding style specified by Section 7 of the SOAP specification, parameters are always wrapped.

The SoapDocumentMethod and the SoapRpcMethod attributes are linked with a particular Web method and you can use them to override the defaults set by their Web service counterparts. In addition, they can be used to further define how messages sent and received by a Web method should be encoded. The SoapRpcMethod attribute supports the same set of properties minus the ParameterStyle and Use properties.

Two of the four message exchange patterns defined by WSDL (request-response and one-way) are supported by ASP.NET. Default message pattern is request-response and so far in this article, we all used this default in the examples. Both the SoapDocumentMethod and the SoapRpcMethod attributes expose the OneWay property. When set to true, this property states that when that particular Web method is invoked, no response will be returned to the client.

With the SoapDocumentMethod and the SoapRpcMethod attributes, you can also specify the name of the element used to wrap the parameters within the request and response messages. ResponseElementName and RequestElementName properties can be set to the name assigned to their respective elements. By setting the RequestNamespace or ResponseNamespace property, you can also set the namespace in which the datatype of the request or response element is defined. The namespace defaults to encodedTypes relative to the Web service's namespace, if this property is not set.

The properties used to set the element name and the namespace of the response and request messages will be ignored if the ParameterStyle property is set to Wrapped. You need to take into account whether the identity of the parameters will be maintained when you pass parameters to a remote service. Maintaining the identity of the parameters is extremely important in some cases. Consider the following Web service:

public struct Person
{
public string Name;
public int Age;
}
public class ReaderOpposition
{
[WebMethod]
public void Register(Person opponent, Person john y)
{
// Implementation...
}
}

The person who will be reading a book as homework is the opponent. If the reader needs to read this book, she will be assigned to it. John is the individual who will be reading the other partner. With that information in mind, consider the following example:

ReadingOpposition opposition = new ReadingOpposition();
Person reader =
new Person();
opposition.Register(reader, reader);

There is an error in this code: a reader is registered as both the opponent and the belay. The reader needs to make sure that she will not need to read! Structures are passed by value by default, therefore the Register method cannot catch this runtime error. As a result, two independent copies of reader will be passed to the Register Web method. The sponsors of the opposition would want to ensure that every reader is being john. However, unless you maintain the identity, the Register method will have no idea whether the opponent and the john are the same. I will explain two potential ways of solving this problem.

The first way is to pass a unique identifier with each of the entities. For example, you might want to pass the person's driver's license number in addition to passing the person's name and age. Then the implementation of the Register method could check to ensure that the license number of the opponent and john are not the same.
To pass the instance of the Person structure by reference is the second way to solve this problem. The use of the href and id attributes to maintain the identity of a parameter passed by reference is specified by SOAP Encoding. ASP.NET controls this mechanism to maintain the identities of instances of structures that are passed by reference. Let us look at a modified version of the Register method:

public struct Person
{
public string Name;
public int Age;
}
public class ReadingOpposition
{
[WebMethod]
[SoapRpcMethod]
public void Register(ref Person opponent, ref Person john)
{
// Verify that the opponent and the john
// are not the same person.
if(Object.ReferenceEquals(opponent, john))
{
throw new SoapException(
"The opponent and the john cannot be the same person.",
SoapException.ClientFaultCode);
}
// Implementation...
}
}

In the preceding example, the Register Web method is decorated with the SoapRpcMethod attribute. This instructs the ASP.NET runtime to serialize the parameters using SOAP. In addition, each parameter is decorated with the ref keyword, which indicates that the parameter will be passed by reference. This instructs the ASP.NET runtime to maintain the identity of the instance of the structure passed to the Register method. Note that ASP.NET will maintain identity only for Web methods decorated with the SoapRpcMethod attribute or contained within a class decorated with the SoapRpcService attribute.

Unfortunately, when handling parameters passed by reference, to some extent ASP.NET is not in agreement. There is one case in which the identity of parameters passed by reference is not maintained by ASP.NET. There is another case in which the identity is maintained, but modifications to the parameters passed by reference are not passed back to the caller. We will study each of these conditions independently. With the first issue, the ASP.NET runtime does not properly maintain the identity of parameters when core value types such as Int32 and String are passed by reference. Consider the following example:

public class Issues
{
[WebMethod]
[SoapRpcMethod]
public void Xy(ref int x, ref int y)
{
x += 10;
y += 30;
}
}

Because both x and y are bedecked with the ref keyword, their values will be round- tripped to the caller. Therefore, any changes made to the values of x and y by the Xy Web method will be reflected on the client. However, since the identities of the parameters are not maintained, your application could be left in an inconsistent status. Consider the following client code:

Issues issues = new Issues();
int z = 10;
issues.Xy(
ref z, ref z);

This code leverages a proxy class generated by the ASP.NET WSDL.exe command line utility and generates the following SOAP request message:

<?xml version="1.0" encoding="utf-8"?>
<
soap:Envelope xmlns:soap=http://schemas.xmlsoap.org/ soap/envelope/
xmlns
:soapenc=http://schemas.xmlsoap.org/soap/encoding/
xmlns
:tns=http://tempuri.org/
xmlns:types=http://tempuri.org/encodedTypes
xmlns
:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns
:xsd="http://www.w3.org/2001/XMLSchema">
<
soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/ encoding/">
<
tns:Xy>
<
x xsi:type="xsd:int">10</x>
<
y xsi:type="xsd:int">10</y>
</
tns:Xy>
</
soap:Body>
</
soap:Envelope>

As you may notice, two different imitations of the value of z were encoded into the request message. However, the Xy Web method cannot tell that the parameters x and y actually point to the same variable z on the client. Therefore it will act on x and y independently. If identity were maintained, z would equal 50 because of calling Xy. Since identity was not maintained, x is set equal to 20 and y is set equal to 40, as shown in the resulting SOAP response message:

<?xml version="1.0" encoding="utf-8"?>
<
soap:Envelope xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/
xmlns
:soapenc=http://schemas.xmlsoap.org/soap/encoding/
xmlns
:tns=http://tempuri.org/
xmlns:types=http://tempuri.org/encodedTypes
xmlns
:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns
:xsd="http://www.w3.org/2001/XMLSchema">
<
soap:Body
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<
tns:XyResponse>
<
x xsi:type="xsd:int">20</x>
<
y xsi:type="xsd:int">40</y>
</
tns:XyResponse>
</
soap:Body>
</
soap:Envelope>

The ASP.NET-generated proxy will first set z equal to 20 and then set z equal to 40. As a result, instead of the correct value of 50, the final state of z will be 40. One possible workaround is to wrap the common value type within a structure. The following example demonstrates this technique:

public class Issues
{
public struct Parameter
{
public int Value;
}
[WebMethod]
[SoapRpcMethod]
public void Xy(ref Parameter x, ref Parameter y )
{
x.Value += 10;
y.Value += 30;
}
}

Contrasting core value types, the ASP.NET runtime maintains the identity of an instance of a structure that is passed by reference. However, the ASP.NET runtime also maintains the identity of an instance of a structure that is passed by value. Therefore, the preceding example will exhibit the same behavior even if the ref keyword is specified. You can decorate the Web method with the SoapDocumentMethod parameter instead of the SoapRpcMethod parameter if you do not want the identities of the parameters to be maintained.

The last subject is that the ASP.NET runtime will serialize .NET reference types in only the SOAP request message and not the response message. By default, reference types are passed by reference to a method. To accomplish this performance, the client needs to receive the state of the reference type after the message has returned. On the other hand, the client does not have sufficient information to update its variables accordingly, since the ASP.NET runtime will not serialize parameters that contain instances of reference types in the return SOAP response message.

You need to decorate the parameter with the ref keyword if you want parameters containing instances of reference types to be passed by reference. Parameters that contain instances of reference types that are decorated with the ref keyword will be serialized in both the SOAP request message and the response message.
Now we completed this task, it is helpful to have a means by which to pass data contained in reference types one way across the wire to reduce the total of data sent. However, we should achieve this without overloading the meaning of existing keywords. Whether the code is executed locally or remotely, the meanings of keywords should be the same.

SOAP-RPC

SOAP messages are basically one-way transmissions from a sender to a receiver. However they are often combined to implement request/response mechanisms. A few conventions must be followed to do RPC using SOAP. At first, request and response messages must be encoded as structures. There must be an element (or member of the input structure) with the same name as the parameter for each input parameter of an operation. In addition, there must be an element with a matching name for every output parameter.

Here is a reduced, RPC-based view of the SOAP message. Only the body portions of the SOAP request and response envelopes are shown.

Request
<SOAP-ENV:Body>
<
m:GetLastTradePrice xmlns:m="some-URI">
<
symbol>DEF</Symbol>
</
m:GetLastTradePrice>
</
SOAP-ENV:Body>

Response

<SOAP-ENV:Body>
<
m:GetLastTradePriceResponse xmlns:m="some-URI">
<
price>22.50</price>
</
m: GetLastTradePriceResponse>
</
SOAP-ENV:Body>

The request invokes the GetLastTradePrice method. Pay attention to the response that defines a GetLastTradePriceResponse operation. To create a Response structure a convention common to SOAP calls for appending Response to the end of a Request operation. This output structure has a price element, which returns the results of the method invocation, most likely as a float. It is important to notice that data types nowhere in the SOAP envelope are explicitly outlined. Therefore, just by looking at the SOAP message, we do not know what type the symbol is or the type of the result parameter price. Client applications define data types either generically through encodings, or privately via agreed-upon contracts with servers. In either case, these definitions are not explicitly included in the SOAP message.

Finally, a lower-level protocol like HTTP is needed, in order to do RPC. SOAP 1.1 1 (and its sister specification "SOAP Message with Attachments") permit the use of FTP, SMTP or even (possibly) raw TCP/IP sockets, even though the SOAP 1.0 specification mandated the use of HTTP as the transport protocol. All the serialization and encoding rules general to SOAP apply to RPC parameters as well.

SOAP Serialization

The objects being serialized are persisted as XML in both SOAP serialization and in XML serialization. However, the similarity ends there. The use for SOAP serialization reside in the System.Runtime.Serialization namespace rather than the System.Xml.Serialization namespace used by XML serialization. For serialization, the run-time serialization classes use a completely different mechanism than the XmlSerializer class.

SOAP serialization has several benefits. It creates a fully SOAP-compliant envelope and any system or service that understands SOAP can process it. Also, SOAP serialization supports either objects that implement the ISerializable interface to manage their own serialization, or objects that are marked with the SerializableAttribute attribute. Also, it can deserialize a SOAP envelope into a compatible set of objects. Additionally, it can serialize and restore non-public and public members of an object.

In SOAP message how data is serialized is vitally important. Data must be serialized both for method parameters and for data returned from successful method calls. To represent data types, all systems must agree on a standard way, thus the SOAP specification explicitly states how each type of data is serialized in a SOAP message. Therefore, at the end, any data can be transformed into a valid SOAP message and sent over HTTP to a web service or back to a client. The mainstream of the serialization rules come from the XML Schema standard. For example, presume that we have a method with the following line that computes the discount for an order.

float ComputeDiscount(string Name, int OrderNumber, float TotalCost);
The SOAP message will sent to this web service looks like this:

Request
<SOAP-ENV:Body>
<
m:GetLastTradePrice xmlns:m="some-URI">
<
symbol>DEF</Symbol>
</
m:GetLastTradePrice>
</
SOAP-ENV:Body>

Response

<
SOAP-ENV:Body>
<
m:GetLastTradePriceResponse xmlns:m="some-URI">
price>22.50</price>
</m: GetLastTradePriceResponse>
</
SOAP-ENV:Body>

Many of the common data types that are available in most programming languages such as string, boolean, float, int, datetime, binary are listed in the XML Schema specification. The important question is how the method name becomes a qualified element in the Body element. Inside each parameter is listed as a typed element.
If all method calls were this trivial, evidently, this would be very simple. However, SOAP must be able to serialize complex method calls with any parameters to be truly vigorous and flexible standard. One common example is a method that accepts an object. To serialize an object into an XML format there needs to be a way so the receiving web service can utilize that object. To serialize complex data objects, SOAP uses a very simple format. The name of the object is used as the outmost element, with each data element contained in a typed sub-element. Therefore, here is an example object:

public struct book
{
public string Isbn;
public string Title;
public string Author;
public float price;
}

We can serialize this in a SOAP message, than we need to call the following method on a remote web service:

Boolean BuyBook(Book, aBook);

Moreover, here is the serialized object in the message:

<SOAP-ENV:Envelope
xmlns
:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<
SOAP-ENV:Body
xmlns:bookStore="http://www.godelpublishing.com">
<
bookStore:BuyBook>
<
Book>
<
Isbn xsi:type="string">4531454334</Isbn>
<
Title xsi:type="string">Advanced Web
Services
</Title>
<
Author xsi:type="string">John Godel</Author>
<
Price xsi:type="float">59.99</Price>
</
Book>
</
bookStore:BuyBook>
</
SOAP-ENV:Body>
</
SOAP-ENV:Envelope>

SOAP also enables you with the serialization of arrays. Suppose we need to call a web service with the following line:

void SortArray(int[] nArray);

The SOAP message to send to this web service would look like this:

<SOAP-ENV:Envelope
xmlns
::SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/
xmlns::SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/
xmlns:xsi="http//www.w3.org/2001/XMLSchema/instance">
<SOAP-ENV:Body xmlns:sort="URI">
<
sort:SortArray>
<
SOAP-ENC:Array SOAP-ENC:ArrayType="xsi:int[5]">
<
SOAP-ENC:int>3</SOAP-ENC:int>
<
SOAP-ENC:int>1</SOAP-ENC:int>
<
SOAP-ENC:int>5</SOAP-ENC:int>
<
SOAP-ENC:int>4</SOAP-ENC:int>
<
SOAP-ENC:int>2</SOAP-ENC:int>
<
SOAP-ENC:int>6</SOAP-ENC:int>
</
SOAP-ENC:Array>
</sort:SortArray>
</
SOAP-ENV:Body>
</
SOAP-ENV:Envelope>


SOAP encodes array by cover in the SOAP-ENC: Array element. This element must contain a SOAP-ENC: ArrayType attribute that specifies what data type the array is composed of as well as the number of elements contained in the array. Inside of the SOAP-ENC: Array elements are the individual array items as separate elements, with the qualified type of the data as each element name.

To represent data in a SOAP message, the SOAP specification has many more rules and standards. There are number of rules for serialization and we have only discussed the most basic forms.

SOAP Fault

Error and/or status information within a SOAP message is carried by the SOAP Fault element. If present, the SOAP Fault element MUST appear as a body entry and MUST NOT appear more than once within a Body element. Briefly, the response to a SOAP message is a SOAP fault element in the body of the message, when an error occurs during processing, and the fault is returned to the sender of the SOAP message.

The SOAP Fault element defines the following four sub-elements:
<faultcode>

  • The faultcode element is intended to provide an algorithmic mechanism for identifying the fault. The faultcode MUST be present in a SOAP Fault element and the faultcode value MUST be a qualified name as defined in, section 3. SOAP defines a small set of SOAP fault codes covering basic SOAP fault

<faultstring>

  • The faultstring element is proposed to give a human readable explanation of the fault and is not intended for algorithmic processing. The faultstring element is similar to the 'Reason-Phrase' defined by HTTP. It MUST be present in a SOAP Fault element and SHOULD provide at least some information explaining the nature of the fault.

<faultactor>

  • The faultactor element is intended to provide information about who caused the fault to happen within the message path. It is similar to the SOAP actor attribute but instead of indicating the destination of the header entry, it indicates the source of the fault. The value of the faultactor attribute is a URI identifying the source. Applications that do not act as the ultimate destination of the SOAP message MUST include the faultactor element in a SOAP Fault element. The ultimate destination of a message MAY use the faultactor element to indicate explicitly that it generated the fault.

<detail>

  • The detail element is intended for carrying application specific error information related to the Body element. It MUST be present if the contents of the Body element could not be successfully processed. It MUST NOT be used to carry information about error information belonging to header entries. Detailed error information belonging to header entries must be carried within header entries.

The absence of the detail element in the Fault element indicates that the fault is not related to processing of the Body element. This can be used to distinguish whether the Body element was processed or not in case of a fault situation.

All immediate child elements of the detail element are called detail entries and each detail entry is encoded as an independent element within the detail element.

The encoding rules for detail entries are as follows:

  • A detail entry is identified by its fully qualified element name, which consists of the namespace URI and the local name. Immediate child elements of the detail element MAY be namespace-qualified.
  • The SOAP encodingStyle attribute MAY be used to indicate the encoding style used for the detail entries.

Fault codes are defined in the SOAP envelope schema, for instance:

HTTP/1.1 500 Internal Server Error
Content-Type: text/xml; charset="utf-8"
Content-Length: nnn
<env:Envolope xmlns:env="http:://schemas.xmlsoap.org/soap/envelope">
<
env:Header>
<
V:Upgrade xmlns:V="http://www.w3.org/2001/12/
soap-upgrade">
<
envelope qname="namesp1:Envelope"
xmlns:namesp1="http://www.w3.org/2001/12/
soap-envelope"
</
envelope>
</
V:Upgrade>
<
env:Header>
<
env:Body>
<
env:Fault>
<
faultcode>env:VersionMismatch</faultcode>
<
faultstring>Version mismatch</faultstring>
</
env:Fault>
</
env:Body>
</
env:Envelope>

Other Fault sub-elements MAY be present, provided they are namespace-qualified.

SOAP Fault Codes

When describing faults defined by this specification, the faultcode values defined in this section must be used in the faultcode element. The namespace identifier for these faultcode values is "http:://schemas.xmlsoap.org/soap/envelope"
. Use of this space is recommended (but not requisite) in the specification of methods defined outside of the present specification.
The default SOAP faultcode values are defined in an extensible way so while maintaining backwards compatibility with existing faultcode values, it will allow new SOAP faultcode values to be defined. The mechanism used is very similar to the 1xx, 2xx, 3xx etc basic status classes defined in HTTP. However, they are defined as XML qualified names instead of integers. The character "." is used as a separator of faultcode values which indicates that what is to the left of the dot is a more generic fault code value than the value to the right. Example:

Client.Authentication

The set of faultcode values defined in this document is:

Name Meaning
VersionMismatch The processing party found an invalid namespace for the SOAP Envelope element
MustUnderstand An immediate child element of the SOAP Header element that was either not understood or not obyed by the processing party conatained a SOAP must understand attribute with a value of "1".
Client The Client classof errors indicates the message that wasincorrectly formed or did not contain the appropriate information in order to succeed. For example, the message could lack the proper authentication or payement information. It is generally an indication that the messgae should not  be resent without change.
Server The Server class of errors indicates that the message could not be processed for reasons not directly attributable to the contents of the message itself but rather to the processing of the message.For example, processing could not include communicatingwith an upstream processor, which did not respond. The messgae may suucceed at a later point in time. 

Next Recommended Readings