Click here to Skip to main content
15,886,919 members
Articles / Web Development / ASP.NET
Article

Exception Handling SOAP Extension

Rate me:
Please Sign up or sign in to vote.
4.00/5 (7 votes)
6 Jun 20053 min read 97.6K   2K   31   8
SOAP Extension to transport full exception information from server to client.

Introduction

My main project at work involves a fairly large application using Windows Forms as the front end, communicating via Web Services with business logic and data access code on the server. I’ve found it very troublesome to track down the cause of unhandled exceptions on the server side, because of the limited exception information you get back in the SOAP message, so I have created a SOAP extension to provide more information.

How it Works

This is a fairly simple piece of code, the SOAP extension listens to every message which is passed between the two machines. If an exception is detected in a response about to be sent back to the client, the extension notices this, and gets the full information about the exception, which it inserts into the XML stream heading back for the client.

The client, after receiving the SOAP response, will notice that an exception is present in the stream, and again the extension will step in to retrieve the additional information which we inserted into the stream on the server. Once it has this, it throws a new exception containing that extended information.

The ProcessMessage method is at the heart of any SOAP extension, it gets called before and after (de)serialization on the server and the client for both the request and the response. Its job is to copy information between the input and output streams at the correct points, and optionally step in and examine or manipulate the SOAP message. Our implementation of it looks like this:

VB
Public Overrides Sub ProcessMessage( _
    ByVal message As System.Web.Services.Protocols.SoapMessage)

    Select Case message.Stage
        Case SoapMessageStage.BeforeSerialize
            'Do nothing
    
        Case SoapMessageStage.AfterSerialize
            'If exception present in message, write details 
            'to the new stream
            If Not message.Exception Is Nothing Then
                InsertExceptionDetails(message.Exception)
            End If

            'Copy new stream to old stream
            newStream.Position = 0
            StreamCopy(newStream, oldStream)

        Case SoapMessageStage.BeforeDeserialize
            'Copy old stream to new stream
            StreamCopy(oldStream, newStream)
            newStream.Position = 0

        Case SoapMessageStage.AfterDeserialize
            'If exception present in message,
            'get details from stream and throw to caller
            If Not message.Exception Is Nothing Then
                Dim DetailString As String
                DetailString = GetExceptionDetails()

                Throw New Exception(DetailString)
            End If

        Case Else
            Throw New ArgumentException("Invalid message stage")

    End Select
End Sub

The other significant methods in this class are called InsertExceptionDetails and GetExceptionDetails. They are responsible for the task of inserting the extended exception information into the stream, and retrieving it. The extended information is inserted into an XML element called ExtendedExceptionDetails within the standard soap:Fault element.

InsertExceptionDetails implementation:

VB
''' <summary>
''' Insert details of the specified exception 
''' into the output stream
''' </summary>
''' <param name="ex">Exception to write details for</param>
Private Sub InsertExceptionDetails(ByVal ex As Exception)
    'Read output stream into XML document
    newStream.Position = 0
    Dim Reader As New XmlTextReader(newStream)
    Dim MessageDoc As New XmlDocument
    MessageDoc.Load(Reader)

    Dim NsMgr As New XmlNamespaceManager(MessageDoc.NameTable)
    NsMgr.AddNamespace("soap", _
        "http://schemas.xmlsoap.org/soap/envelope/")

    'Construct string describing exception
    Dim ErrorInfo As String
    ErrorInfo = ex.ToString()

    'Find existing soap:Fault node describing exception
    Dim ExceptionNode As XmlNode
    ExceptionNode = MessageDoc.SelectSingleNode( _
        "//soap:Fault", NsMgr)

    'Add extended exception detail node to Fault node
    Dim ExceptionDetail As XmlElement
    ExceptionDetail = MessageDoc.CreateElement( _
        "ExtendedExceptionDetails")

    ExceptionDetail.InnerText = ErrorInfo

    ExceptionNode.AppendChild(ExceptionDetail)

    'Write XML document back to output stream
    newStream = New MemoryStream
    MessageDoc.Save(newStream)
End Sub

GetExceptionDetails implementation:

VB
''' <summary>
''' Reads extra exception information from stream and
''' returns it as a string
''' </summary>
''' <returns>Details of any exception detail found in
''' the input stream</returns>
Private Function GetExceptionDetails() As String
    'Read input stream into XML document
    newStream.Position = 0
    Dim Reader As New XmlTextReader(newStream)
    Dim MessageDoc As New XmlDocument
    MessageDoc.Load(Reader)

    Dim NsMgr As New XmlNamespaceManager(MessageDoc.NameTable)
    NsMgr.AddNamespace("soap", _
         "http://schemas.xmlsoap.org/soap/envelope/")

    'Find extended exception detail node
    Dim ExceptionDetailNode As XmlNode
    ExceptionDetailNode = MessageDoc.SelectSingleNode( _
        "//soap:Fault/ExtendedExceptionDetails", NsMgr)

    'Return detail text if found, empty string otherwise
    If Not ExceptionDetailNode Is Nothing Then
        Return ExceptionDetailNode.InnerText
    Else
        Return ""
    End If

End Function

Using the code

To use the code, add references to the ExceptionHandlingSoapExtension assembly, in both the client and web service projects. Add the following section to both App.Config (on the client) and Web.Config (on the server):

XML
<webServices>
    <soapExtensionTypes>
        <add 
            group="0" 
            priority="1" 
            type="ExceptionHandlingSoapExtension.
                ExceptionManagementSoapExtension,
                ExceptionHandlingSoapExtension" 
        />
    </soapExtensionTypes>
</webServices>

This code instructs ASP.NET on both the client and server to use this SOAP extension to process messages.

With the SOAP extension set up, every time an exception occurs during the execution of a web method, an exception will be thrown on the client which will have the message field populated with a full stack trace showing what happened on the server.

Standard exception information

Screenshot showing the standard information returned from a web method exception.

Extended exception information

Screenshot showing the extended information returned courtesy of the SOAP extension.

Real-World Usage

Security

It would be quite a security risk to have publicly accessible web services set up like this; exposing information about the internal workings of your web services can be very useful to malicious users, and a full stack trace exposes a lot! We use this extension in conjunction with various encryption and authentication systems, and the web services are not made accessible on the public Internet so there is little danger of this information falling into the wrong hands.

Cross-platform usage

I believe that non .NET clients consuming web services with this extension will simply ignore the additional exception information, however I cannot guarantee this. In my case, the web services we create will never be accessed by clients other than those we develop so I have not investigated this.

Conclusion

I think it's debatable whether Web Services are the right choice for the type of application I'm developing, but the choice was made well before I started work on the project.

Learning how to write a SOAP extension was interesting for me, I found the MSDN documentation a little misleading to say the least, but they are certainly a simple and powerful way to manipulate web service messages.

I hope this article is helpful to somebody, and I would welcome any feedback - I know I still have a lot to learn!

History

  • 06/06/2005: Created.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSoap Exception in WSDL Pin
Sameer Narkar19-Feb-08 21:06
Sameer Narkar19-Feb-08 21:06 
GeneralSimilar article "User Friendly ASP.NET Exception Handling" [modified] Pin
Michael Freidgeim31-Oct-07 18:06
Michael Freidgeim31-Oct-07 18:06 
GeneralRe: Similar article "User Friendly ASP.NET Exception Handling" Pin
Carl Reid29-May-08 5:28
Carl Reid29-May-08 5:28 
GeneralRe: Similar article "User Friendly ASP.NET Exception Handling" Pin
Michael Freidgeim29-May-08 9:23
Michael Freidgeim29-May-08 9:23 
GeneralAdditional improvements Pin
Ramon de Klein26-Jun-05 4:24
Ramon de Klein26-Jun-05 4:24 
GeneralUse dataset for message details Pin
Renatas16-Jun-05 3:04
Renatas16-Jun-05 3:04 
QuestionThrowing SoapException? Pin
KennS14-Jun-05 17:12
KennS14-Jun-05 17:12 
AnswerRe: Throwing SoapException? Pin
Jon Merrifield14-Jun-05 23:25
Jon Merrifield14-Jun-05 23:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.