Handling and Throwing Exceptions in XML Web Services

Exceptions thrown by an XML Web service method created using ASP.NET are sent back to the client in the form of a SOAP fault. A SOAP fault is a <Fault> XML element within a SOAP message that specifies when an error occurred. When passing a SOAP fault, ASP.NET follows the method prescribed for propagating errors back to a client by the SOAP specification. The SOAP <Fault> XML element contains details such as the exception string and the source of the exception. For details on SOAP faults, see the W3C Web site (http://www.w3.org/TR/SOAP).

Fortunately, both clients and XML Web services created using ASP.NET do not populate or parse the <Fault> XML element directly, but rather use the common design pattern for throwing and catching exceptions in the .NET Framework. An XML Web service can either throw an exception specific to the problem, such as an ArgumentOutOfRangeException or SoapException. Either way, ASP.NET serializes the exception into a valid SOAP message by placing the exception into a SOAP fault element. When the SOAP message is deserialized on an ASP.NET client, the SOAP fault is converted to a SoapException exception, with the exception details placed in the Message property. A client can thus set up a Try/Catch block to catch a SoapException.

A Web application can be comprised of multiple XML Web services, however the Application_Error event within the Global.asax file cannot be used for global exception handling. The HttpHandler for XML Web services consumes any exception that occurs while an XML Web service is executing and turns it into a SOAP fault prior to the Application_Error event is called. Build a SOAP extension to process XML Web service exceptions in a global exception handler. A SOAP extension can check for the existence of an exception in the ProcessMessage method. Within the ProcessMessage method, check the Exception property of the SoapMessage passed when the Stage property is set to AfterSerialize. For details on SOAP extensions, see Altering the SOAP Message Using SOAP Extensions.

Throwing Exceptions from an XML Web Service Created Using ASP.NET

Propagating errors back to a client is done by throwing exceptions. An XML Web service method can do this four ways:

  1. Throw a SoapException exception.
  2. Throw a SoapHeaderException exception.
  3. Throw an exception specific to the problem.
  4. Allow ASP.NET to throw the exception.

The following table describes the exceptions an XML Web service can explicitly throw and how an ASP.NET client receives each exception.

Type of Exception thrown What an XML Web service can do
Exception other than SoapException and SoapHeaderException An XML Web service method detects an exception case and throws the specific exception, such as ArgumentOutOfRangeException, back to the client. An ASP.NET client receives a SoapException with the details serialized into text in the Message property.
SoapException An XML Web service method detects an exception case and throws a SoapException. It also provides additional details regarding the problem. The XML Web service method populates the Detail property to provide this additional information. An ASP.NET client receives the SoapException with the additional information.
SoapHeaderException An XML Web service method detects an exception case while processing a SOAP header. The XML Web service method must throw a SoapHeaderException back to the client, according to the SOAP specification. An ASP.NET client receives the SoapHeaderException.

To throw an exception from an XML Web service

  • Throw the exception specific to the problem, such as a SoapException, or SoapHeaderException, as described in the previous table.

    The following code example throws a SoapException and provides additional details about the exception by setting the Detail property.

    <%@ WebService Language="VB" class="ThrowSoapException"%>
    
    Imports System
    Imports System.Web.Services
    Imports System.Web.Services.Protocols
    Imports System.Xml.Serialization
    Imports System.Xml
    
    Public Class ThrowSoapException
        Inherits WebService
    
        ' This XML Web service method throws a SOAP client fault code. 
        <WebMethod()> _
        Public Sub myThrow()
    
            ' Build the detail element of the SOAP fault.
            Dim doc As New System.Xml.XmlDocument()
            Dim node As System.Xml.XmlNode = _            doc.CreateNode(XmlNodeType.Element, _            SoapException.DetailElementName.Name, _            SoapException.DetailElementName.Namespace)
    
            ' Build specific details for the SoapException.
            ' Add first child of detail XML element.
            Dim details As System.Xml.XmlNode = _             doc.CreateNode(XmlNodeType.Element, _            "mySpecialInfo1", "http://tempuri.org/")
    
            ' Add second child of detail XML element with an attribute.
            Dim details2 As System.Xml.XmlNode = _            doc.CreateNode(XmlNodeType.Element, _            "mySpecialInfo2", "http://tempuri.org/")
            Dim attr As XmlAttribute = doc.CreateAttribute("t", _ 
                "attrName", "http://tempuri.org/")
            attr.Value = "attrValue"
            details2.Attributes.Append(attr)
    
            ' Append the two child elements to the detail node.
            node.AppendChild(details)
            node.AppendChild(details2)
    
            'Throw the exception.
            Dim se As New SoapException("Fault occurred", _            SoapException.ClientFaultCode, _            Context.Request.Url.AbsoluteUri, node)
            Throw se
            Return
        End Sub
    End Class
    [C#]
    <%@ WebService Language="C#" class="ThrowSoapException"%>
    
    using System;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Xml.Serialization;
    using System.Xml;
    
    public class ThrowSoapException : WebService 
    {
        // This XML Web service method throws a SOAP client fault code.
        [WebMethod]
        public void myThrow(){
    
            // Build the detail element of the SOAP fault.
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            System.Xml.XmlNode node = doc.CreateNode(XmlNodeType.Element,             SoapException.DetailElementName.Name,              SoapException.DetailElementName.Namespace);
    
            // Build specific details for the SoapException.
            // Add first child of detail XML element.
            System.Xml.XmlNode details =
              doc.CreateNode(XmlNodeType.Element, "mySpecialInfo1",
                             "http://tempuri.org/");
            System.Xml.XmlNode detailsChild =           doc.CreateNode(XmlNodeType.Element, "childOfSpecialInfo",                         "http://tempuri.org/");
            details.AppendChild(detailsChild);
    
            // Add second child of detail XML element with an attribute.
            System.Xml.XmlNode details2 =          doc.CreateNode(XmlNodeType.Element, "mySpecialInfo2",                         "http://tempuri.org/");
            XmlAttribute attr = doc.CreateAttribute("t", "attrName",
                                "http://tempuri.org/");
            attr.Value = "attrValue";
            details2.Attributes.Append(attr);
    
            // Append the two child elements to the detail node.
            node.AppendChild(details);
            node.AppendChild(details2);
    
            //Throw the exception            SoapException se = new SoapException("Fault occurred",          SoapException.ClientFaultCode,          Context.Request.Url.AbsoluteUri ,          node);
    
            throw se;
            return;
        }
    }
    

To catch an exception thrown by an XML Web service method

  • Within a Try/Catch block, catch the SoapException (any exceptions thrown by an XML Web service method are thrown as a SoapException).

    The following code example of a client calling an XML Web service method catches the exception thrown by the XML Web service method. The client then populates an HTML table with the properties of the caught SoapException.

    <%@ Import Namespace="System.Web.Services.Protocols" %>
    <%@ Import Namespace="System.Xml" %>
    <%@ Page Language="vb" %>
    <html>
     <head>
     <script runat=server language=vb>
        Sub Page_Load(o As Object, e As EventArgs)
           ' Create a new instance of the XML Web service class.
           Dim ThrowsSoapException As ThrowSoapException = New _
                     ThrowSoapException()
           Try
             ThrowsSoapException.myThrow()
           Catch myerr As SoapException
                ' Populate the table with the exception details.
                ErrorTable.Rows.Add(BuildNewRow("Fault Code Namespace", _
                                    myerr.Code.Namespace))
                ErrorTable.Rows.Add(BuildNewRow("Fault Code Name", _
                                    myerr.Code.Name))
                ErrorTable.Rows.Add(BuildNewRow( _
                  "SOAP Actor that threw Exception", myerr.Actor))
                ErrorTable.Rows.Add(BuildNewRow("Error Message", _
                                     myerr.Message))
                ErrorTable.Rows.Add(BuildNewRow("Detail", _
                    HttpUtility.HtmlEncode(myerr.Detail.OuterXml) )) 
                Return
            End Try
        End Sub 'Page_Load
    
        Function BuildNewRow(Cell1Text As String, Cell2Text As String) _
                 As HtmlTableRow
            Dim row As New HtmlTableRow()
            Dim cell1 As New HtmlTableCell()
            Dim cell2 As New HtmlTableCell()
    
            'Set the contents of the two cells.
            cell1.Controls.Add(New LiteralControl(Cell1Text))
            'Add the cells to the row.
            row.Cells.Add(cell1)
    
            cell2.Controls.Add(New LiteralControl(Cell2Text))
    
            'Add the cells to the row.
            row.Cells.Add(cell2)
            Return row
        End Function 'BuildNewRow 
     </script>
     <head>
     <body>
         <table id="ErrorTable" CellPadding=5 CellSpacing=0 Border="1" BorderColor="black" runat="server" />
     </body>
    [C#]
    <%@ Import Namespace="System.Web.Services.Protocols" %>
    <%@ Import Namespace="System.Xml" %>
    <%@ Page Language="C#" %>
    <html>
     <head>
     <script runat=server language=c#>
     void Page_Load(Object o, EventArgs e){
    
       // Create a new instance of the XML Web service proxy class.
       ThrowSoapException throwSoapException = new ThrowSoapException();
    
       // Make a call to the XML Web service method, which throws an
       // exception.
        try
        {
           throwSoapException.myThrow();
        }
        catch (SoapException error)     {
           // Populate the table with the exception details.
           ErrorTable.Rows.Add(BuildNewRow("Fault Code Namespace",
                                            error.Code.Namespace));
           ErrorTable.Rows.Add(BuildNewRow("Fault Code Name",
                                            error.Code.Name)); 
           ErrorTable.Rows.Add(BuildNewRow(
              "SOAP Actor that threw Exception", error.Actor));
           ErrorTable.Rows.Add(BuildNewRow("Error Message",
               error.Message));
           ErrorTable.Rows.Add(BuildNewRow("Detail",
               HttpUtility.HtmlEncode(error.Detail.OuterXml)));
    
           return;
         }
    
     }
    // This populates a row in an HtmlTable.
     HtmlTableRow BuildNewRow(string Cell1Text, string Cell2Text) {
         HtmlTableRow row = new HtmlTableRow();
         HtmlTableCell cell1 = new HtmlTableCell();
         HtmlTableCell cell2 = new HtmlTableCell();
    
         //Set the contents of the two cells.
         cell1.Controls.Add(new LiteralControl(Cell1Text));
         //Add a cell to the row.
         row.Cells.Add(cell1);
    
         cell2.Controls.Add(new LiteralControl(Cell2Text));
    
         //Add a cell to the row.
         row.Cells.Add(cell2);
         return row;
    
     }
     </script>
     <head>
     <body>
         <table id="ErrorTable" CellPadding=5 CellSpacing=0 Border="1" BorderColor="black" runat="server" />
     </body>
    

Exceptions not handled by an XML Web service method

If an XML Web service method does not catch an exception that occurs within the method, the following table outlines how the exception is handled by ASP.NET.

When unhandled exception occurs What ASP.NET does
While executing the XML Web service method The exception is caught by ASP.NET and thrown back to the client. The XML Web service client created using the .NET Framework receives a SoapException with the specific exception placed in the InnerException property.
While processing SOAP headers ASP.NET throws a SoapHeaderException. An XML Web service client created using the .NET Framework receives the SoapHeaderException.

See Also

SoapException Class | SoapHeaderException Class | Handling and Throwing Exceptions | Building XML Web Services Using ASP.NET | Building XML Web Service Clients