Mark Wilson I am the creator of TopXML. I am available for international and local (Australia) contracts. I am a Solution Architect/Business Analyst. I have worked in IT in several countries (NZ, Australia, South Africa, UK) building and training teams for government and very large non-governmental organizations. I am ex-Microsoft Consulting Services. I wrote the first book on Microsoft XML published in 2000 called XML Programming with VB and ASP. Most recently I have been building tools for the SEO industry. Ask me for a 37 point SEO health-checkup for your website.
First posted :
03/24/2008
Times viewed :
399
Creating Fault Messages
In the final step to complete our example we add the capability
to detect exceptions and return fault messages to the receiver class. First, we
add a try-catch block
around the lines processing the received message in the Receive() method from the listing.
For every exception we catch, we create a SoapFault object and serialize it to
send a fault message to the response queue. The <detail> of the fault is
populated from a ServerFault
containing specifics about the exception we caught. To send the SoapFault back
to the caller we re-use the SoapObjectSender
class from the last chapter (listing 13.1), not the SoapRPCMessageSender, because the SoapFault class
does not implement the ISoapMessage
interface.
Listing
public void Receive( int timeout )
{
Message queueMessage;
try
{
queueMessage =
_Queue.Receive(
new TimeSpan( 0, 0,
0, timeout, 0 ) );
try
{
SoapMessage
responseMsg =
ProcessSoapStream(
queueMessage.BodyStream );
if( ( null !=
queueMessage.ResponseQueue )
&& (
null != responseMsg ) )
{
SoapRPCMessageSender sender =
new
SoapRPCMessageSender(queueMessage.ResponseQueue.Path);
sender.Send(
responseMsg );
}
}
catch( Exception ex ) |#1
{ |
SoapObjectSender sender =
new SoapObjectSender(queueMessage.ResponseQueue.Path);
(annotation) <#1 All exceptions occuring while the
message is processed result in a fault response.>
(annotation) <#2 The SoapFault and the ServerFault
classes assist in creating properly formatted fault elements. >
Technically, always setting the faultcode to “Server”, as we do in
the listing above, is not appropriate for all the exception types we can catch
with this exception handler. The faultcode is intended for a server related fault only,
e.g. an application configuration is incorrect, a server could not be reached,
etc. Faults due to content of the message should result in a faultcode
“Client”. In a real world scenario we would implement multiple exception
handlers, for example one handler for a HeaderException, another handler for
a content related exception and a third one for an application exception. Each
handler can set the appropriate faultcode for the response message. But hey, this is
only an example and we are trying to keep it simple.
After all this talk about a fault messages it is really time to
see what one looks like. Listing shows a fault message returned by the class
above.
<message
id="ref-5">Database did not respond.</message>
<stackTrace
id="ref-6"> at
Christoph.SoapSerialization.UserManagementApp.InsertNewUser( User newUser ) in
d:\christoph\c#\soapformatter\UserManagementApp\app.cs:line
37</stackTrace>
<exception
xsi:null="1"/>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Did you notice how the content of the <Body> element yet again looks
slightly different from the message formats we have seen in this chapter? The SoapFormatter
does not serialize a SoapFault
object like a regular object. It knows that the SoapFault corresponds to the Fault
element defined by the SOAP standard. Thus it creates the correct namespace
qualifiers for the <Fault>
tag and the faultcode
value. This message also shows how the SoapFormatter creates a well
structured <detail>
section from our ServerFault object. Even a non-.NET receiver could easily
parse and process this detail section.