Click here to Skip to main content
15,867,594 members
Articles / Database Development / SQL Server / SQL Server 2008

Handling SOAP Exceptions in WCF Based Applications

Rate me:
Please Sign up or sign in to vote.
4.83/5 (5 votes)
4 Sep 2013CPOL15 min read 38.5K   379   12   3
Using a custom exception handler component

Abstract

This document provides insights into an approach to handle SOAP Exceptions thrown by an external Web service in a WCF based application. It becomes challenging for a WCF application to handle such exceptions from an external SOAP or ASMX based web service, as you don’t have any control over it.

Typically, in a distributed application, exceptions that occur remotely on an external system must traverse through process or machine boundaries, before they reach client applications. In case of SOA (Service Oriented Architecture), it would be the service boundary which may exist in the same process or different process and/or machine boundaries. Other than these distribution boundaries, there may also be platform and technology boundaries, thereby necessitating interoperable communication. Services provide well-defined boundaries and communicate using serialized message, as defined in a contract.

The following diagram shows sample architecture of a .NET distributed application

Image 1

Figure 1 - Architecture Diagram of .Net Distributed Application

2 SOAP Faults – An overview

To report exceptions from a service to its caller, the exception too must be serialized to a standard format and wrapped in a message. A SOAP fault is a standard format for transfer of exception between distributed applications and is independent of any technology-specifics like CLR, Java or C++ exceptions. It provides details on the contents of faults such as error code, error message etc and provides guidance on the way that the platforms and technologies should process them. The SOAP specification defines a standard XML format that typically includes sections - header and body. SOAP specifications have two versions – SOAP 1.1 and SOAP 1.2. The following table provides the differences between SOAP 1.1 and SOAP 1.2 faults. Though the element names vary, the content are similar between these versions.

SOAP 1.1SOAP 1.2Description
faultCodeCode Required. Standard code that provides more information about the fault. Predefined fault code values in SOAP 1.1 include:
  • VersionMismatch—Invalid namespace defined in SOAP envelope element. The SOAP envelope must conform to the http://schemas.xmlsoap.org/soap/envelope namespace.
  • MustUnderstand—SOAP header entry not understood by processing party.
  • Client—Message was incorrectly formatted or is missing information.
  • Server—Problem with the server that prevented message from being processed.
faultString ReasonRequired. A string explanation of the fault.
faultactorRoleOptional. URI describing source of fault
detailDetailOptional. More information about the exception
NodeOptional. URI describing the node that caused the failure

3 Why exception handler component?

WCF encapsulates the SOAP fault message into FaultException (System.ServiceModel namespace). In order to ensure that the client knows only the required details about the exception, good approach is to handle through our own custom exception. This approach is especially useful, when you

  • Need a common way to handle exceptions from different interfacing systems
  • Are aware of the kind of error messages or exceptions from a remote web service
  • Do not want to abruptly end the session and fault the client
  • Need the flexibility to make your own choices to handle exceptions. i.e. translate the error messages or show them as-is

In a typical distributed system, the external parties or interfacing systems would publish the errors that the client can expect in response to the various test cases. These errors will have to be first categorized into

  • Business Exceptions
    • These are anticipated exceptions that arise because of the failure of a business case. Mostly, such exceptions would be self-explanatory
    • An example would be that, while querying a data that does not exist, some services might throw exceptions like “Data does not exist”.
    • Technical Exceptions
    • These are technical errors, which don’t allow the execution of the business case. Such exceptions may not be descriptive enough for the user to know what went wrong. Hence they can be chosen to traverse as-is or can be translated to a more meaningful message.
    • Examples would include, issue with execution environment, programming error etc.

The way, the exceptions are thrown, purely depends on the design of the remote web services. They can choose to take an exception path, for a simple failure of a business case, as stated in the above example.

The design of this exception handler component caters to both business and technical exceptions. The design is extensible enough that a set of parameters can be configured at a later point in time. The following sections detail out the design of this component.

The code sample provided as part of this component typically has the same architecture as that of the architecture diagram of .Net distributed application, as depicted in Figure 1. The system under discussion typically interacts with two external systems, which in turn expose web services consumed by WCF application.

4 Architecture

The following UML diagram depicts the logical architecture of a .NET distributed application that is considered to demonstrate the usage of this exception handler component

Image 2

Figure 2 - Logical Architecture Diagram

The exception handler component under our discussion will be a part of Infrastructure architecture layer. The sample code provided as part of the usage of this component realizes this logical architecture of the system. The table below provide the brief description of each layer and its mapping to the respective code artifacts (projects) in Visual Studio solution:

LayersDescriptionRealization
PresentationContains all presentation and user interfaces related aspects of the system as well as client side processingWinFormApplicationInfrastructure.Wcf
ApplicationContains all the business logic and server side processes.WCFService.ServiceContractsWCFService.MessageContractsWCFService.DataContracts
WCFService.FaultContractsWCFService.ServiceImplementationWCFService.Service
InterceptorWCFService.BusinessLogicServiceModel
DomainContains all business domain entity objects. The objects are business model (domain) representation of the dataWCFService.BusinessEntities
Resource AccessContains all the components to access the relevant data store as well as external servicesWCFService.ServiceAgentsDataAccess
DataContains all the system data storesIntegrationSystemDb
InfrastructureContains all the framework components which provide the infrastructure services WCFSoapFaultHandler
IntegrationContains the required components for communicating with external systems.Not Realized

5 Realization of Logical Architecture layers

The following diagram shows the snapshot of the projects in various architecture layers as discussed in the previous section. These projects comprise the code artifacts, delivered as part of the exception handler component.

5.1 Presentation Layer

The presentation layer typically comprises of the form application to interact with the user and Infrastructure.Wcf project which enables us to customize service or endpoint behaviors on the client-side.

Image 3

Figure 3 - Presentation Layer

5.2 Application Layer

Application layer provides all business logic execution and server side processing. The WCF service acts as the gateway for this layer.

5.2.1 Service Layer

Service layer exposes the business logic as services. It is an abstraction on top of the business logic layer. The service interacts with the domain and presentation layer using the message contracts. WSSF (Web Service Software factory) is used for modelling the services.

The following diagram shows the snapshot of service contracts, message contracts, data & fault contracts, Service Interceptor and Service model used to model WCF services

Image 4

Figure 4 - Service Layer

5.3.1 Business Logic Layer

Business action provides the business logic execution. The following diagram shows the classes involved in business logic layer.

Image 5

Figure 5 - Business Logic Layer

5.3 Domain Layer

The domain layer typically comprises of business entities. In our system under consideration, there are no business entities being created. Still, the solution provides the respective layer that can be used in future.

Image 6

Figure 6 - Domain Layer

5.4 Resource Access Layer

This layer typically contains the service agents used to communicate with the external systems and data access layer, if any. In the system under consideration, the service agents holds the proxies of the respective web services of the external systems.

Image 7

Figure 7 - Resource Access Layer

5.5 Infrastructure Layer

This layer comprises of all framework components that provide architecture services. The exception handler component, WCFSoapFaultHandler will be a part of this layer.

Image 8

Figure 8 - Infrastructure Layer

5.6 Data Layer

The data layer contains the actual data stores. The following diagram shows the snapshot of the database project created for the system under discussion. It contains all the required database scripts and objects required to create the database.

Image 9

Figure 9 - Data Layer

6 Data Model

The following diagram depicts the physical data model designed for this component.

Image 10

Figure 10 - Data Model

3 tables are involved in this data model.

  1. IntegrationSystem

    This table typically holds details about the different external interfacing systems that your client application interacts with and will have to handle exceptions from these systems.

  2. IntegrationSystemMessage

    This table contains the important details about the exception such as the unique error code for SOAP fault and the below configurable parameters to handle the exception.

    1. CmspMessageId – A custom message Id that replaces the original exception message.
    2. Code – Error code in SOAP fault to match with one or more specific exceptions.
    3. Match – This parameter specifies, if the exception detail is to be matched with any of the following options
      1. Exact – one-to-one mapping between error code in SOAP fault and Code column in this table
      2. Range – Code column in the table will contain a range of error code values (example: 25 to 72 expressed as ‘25_72’)
      3. All – There may be only one record with this option, for an external system. This is useful, if you want to apply the same configuration and pattern for all exceptions from that external interfacing system.
  3. IntegrationSystemMessageDisplayType

    This table holds the configuration details to decide, how the exception message is to be displayed to the end user. It specifies, if the fault is to be translated or not. It also details the pattern of translation. It can have the following values.

    1. IntegrationMessage - No translation of the error message in SOAP fault
    2. CmspMessage – Error message in SOAP fault is completely replaced by custom message
    3. CmspMessageWithIntegrationMessage – Partial translation of error message in SOAP fault such that custom message also contains original error message
    4. CmspMessageWithIntegrationMessageAndCode – Partial translation of error message in SOAP fault such that custom message also contains original error message and error code.

7 Detailed design of the component

The exception handler component is designed to handle SOAP faults.

Image 11

Figure 11 - Design of Exception Handler Component

Typically, when a SOAP exception is thrown by an external web service, a WCF service can choose to handle the exceptions in multiple ways. It can be handled by

  • Defining fault contracts - Recommended, when the types are known.
  • Defining custom exceptions - Recommended when the types are unknown.

The exception handler under our discussion takes the option of defining custom exceptions.

As soon as an exception is received by the handler component, it looks up for the details of it in the SOAP fault XML. Depending on SOAP Fault versions, it is easier or complex to get the details of the exception.

For instance, you can easily look up the error code from the code and Reason nodes in SOAP fault XML, provided, the exception information is available in these nodes. Sometimes, one may have to dig into the details section of the SOAP fault to get the actual information about the exception. Unfortunately, there is no easy way to access the detail element from FaultException. MessageFault class will have to be used in order to interact with the fault message and retrieve its details.

One may know the structure of the SOAP fault XML in advance as it depends on the configuration of SOAP faults in the external systems. Once the pattern is identified, different overloads of the exception handler component can be used to read the exception information from the respective nodes in SOAP fault XML.

Once the details of the exception is read from SOAP fault XML, the error code is looked up in the database table, to see, if this exception is to be translated to a business exception or not. A stored procedure is being used, to look up this data at the database table. According to the configuration made at the database end, the exception can be customized to a different business message or chosen to be left as-is.

The exception handler component finally throws a new custom exception, ‘IntegrationException’, with all the required details of translation as applicable. The above class diagram shows the design of the custom IntegrationException. The client can check the type of the exception and take appropriate action to show the message to the end-user.

The class diagram above also shows a class by name ‘FaultDetailNodes’. This class is created to hold the details of SOAP fault, especially the detail node. The details like name of the fault detail node, order of the nodes to look for, can be configured using this class, for every integration point.

8 Handling of SOAP exception at WCF interceptor

The exceptions are mostly handled using a try-catch block in an application. A more robust way to handle such SOAP exceptions from an external web service is to handle them at the WCF interceptor layer. An inspector behavior can be created for every integration point, to enable inspection or modification of a message before the service request is being sent and after the response is being received.

In the system under discussion, there are two external systems, Bis1 and Bis2, with which the WCF service interacts with. These external systems expose web services that are typically consumed by WCF service. For illustration, these web services are designed to throw SOAP faults. Bis2 system is designed to create a SOAP fault, where the exception information is available in the details node, whereas Bis1 system is designed to throw a simple SOAP fault with no exception information in details node.

As can be seen in Figure 4 - Service Layer, two inspector behaviors are created within the Service Interceptor project, one each for the external system.

These service interceptors are configured in web.config to intercept the respective service calls. A sample of, how these interceptors are being configured is shown below:

Image 12

In order to explicitly control the behavior of the application, when SOAP faults are generated and to perform WCF custom exception handling and shielding, ExtendedServiceErrorHandler class is created that implement the interface IErrorHandler.

A sample of how a SOAP exception is being handled at WCF interceptor using the exception handler component is shown below:

C#
namespace WCFService.ServiceInterceptor
{
    /// <summary>
    /// behavior to intercept integration service calls
    /// </summary>
    public class Bis2ServiceInspectorBehavior : 
           BehaviorExtensionElement, IEndpointBehavior, IClientMessageInspector
    {
        private const string ErrorCodeNode = "ErrorCode";
        private const string ErrorMessageNode = "Message";  
        /// <summary>
        /// Read only property to obtain the type of behaviour
        /// </summary>
        public override Type BehaviorType
        {

            get { return typeof(FileNetServiceInspectorBehavior); }
        }

        /// <summary>
        ///  Creates a behavior extension based on the current configuration settings.
        ///  Overridden from base to return the custom behaviour
        /// </summary>
        /// <returns>Tyhe custom behaviour object.</returns>
        protected override object CreateBehavior()
        {
            return new FileNetServiceInspectorBehavior();
        }

        #region IEndpointBehavior Members

        /// <summary>
        /// Implement to pass data at runtime to bindings to support custom behavior.
        /// </summary>
        /// <param name="endpoint">The endpoint to modify.</param>
        /// <param name="bindingParameters">The objects that
        /// binding elements require to support the behavior.</param>
        void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, 
               System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            // No implementation required
            return;
        }
        /// <summary>
        /// Implements a modification or extension of the client across an endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint that is to be customized.</param>
        /// <param name="clientRuntime">The client runtime to be customized.</param>
        void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(this);
        }

        /// <summary>
        /// Implements a modification or extension of the service across an endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint that exposes the contract.</param>
        /// <param name="endpointDispatcher">The endpoint dispatcher to be modified or extended.</param>
        void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        { }
        /// <summary>
        /// Implement to confirm that the endpoint meets some intended criteria.
        /// </summary>
        /// <param name="endpoint">The endpoint to validate.</param>
        void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
        { }


        #endregion
                
        #region IClientMessageInspector Members

        /// <summary>
        /// Enables inspection or modification of a message after a reply message
        /// is received but prior to passing it back to the client application.
        /// </summary>
        /// <param name="reply">The message to be transformed
        /// into types and handed back to the client application.</param>
        /// <param name="correlationState">Correlation state data.</param>
        void IClientMessageInspector.AfterReceiveReply(
             ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            if (reply.IsFault)
            {
                //Create detail Nodes
                List<FaultDetailNodes> faultDetailNodesList = new List<FaultDetailNodes>();
                faultDetailNodesList.Add(new FaultDetailNodes(ErrorMessageNode, false, 1));
                faultDetailNodesList.Add(new FaultDetailNodes(ErrorCodeNode, true, 2));

                //Create message fault from Message,
                //create fault exception from message fault and handle the exception
                MessageFault fault = MessageFault.CreateFault(reply, Int32.MaxValue);
                FaultException faultException = new FaultException(fault);
                IntegrationExceptionHandler.HandleSoapFault11(faultException, 
                          Enums.IntegrationSystem.Bis2, faultDetailNodesList);                
            }
        }

        /// <summary>
        /// Enables inspection or modification of a message before a request message is sent to a service.
        /// </summary>
        /// <param name="request">The message to be sent to the service.</param>
        /// <param name="channel">The WCF client object channel.</param>
        /// <returns>
        /// The object that is returned as the <paramref name="correlationState
        /// "/>argument of the <see cref="M:System.ServiceModel.Dispatcher.
        /// IClientMessageInspector.AfterReceiveReply(System.ServiceModel.Channels.Message@,
        /// System.Object)"/> method. This is null if no correlation state is used.
        /// The best practice is to make this a <see cref="T:System.Guid"/>
        /// to ensure that no two <paramref name="correlationState"/> objects are the same.
        /// </returns>
        object IClientMessageInspector.BeforeSendRequest(ref 
          System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {            
            return null;
        }      
        
        #endregion

    }
 }

The code snippet in AfterReceiveReply method creates a fault exception from the message fault and uses the exception handler component to handle soap fault exception.

9 Handling of custom exception at the client side

With the use of this exception handler component, all SOAP exceptions from external web services will be translated to custom exception ‘IntegrationException, before it reaches the client-side. Based on the configuration details available in the custom exception, the appropriate error message is shown to the user. These configuration details of the exception are stored in IDictionary collection of the exception object.

A sample code snippet of how these exceptions details are translated to appropriate error messages to end-user is shown below:

C#
/// <summary>
/// Handles the exception.
/// </summary>
/// <param name="ex">The Exception.</param>
private static void HandleException(Exception ex)
{
     DialogResult result = DialogResult.None;
     if (ex.GetType() == typeof(IntegrationException))
     {
        IntegrationException integrationException = (IntegrationException)ex;
        int messageDisplayType = 
          Convert.ToInt32(GetExceptionData(integrationException.Data, Constant.MessageDisplayType));

        switch (messageDisplayType)
        {
            case (int)Enums.IntegrationSystemMessageDisplayType.IntegrationMessage:
                result = CustomMessageBox.Show(GetExceptionData(integrationException.Data, Constant.ErrorMessageNode));
                return;
            case (int)Enums.IntegrationSystemMessageDisplayType.CmspMessage:
                result = CustomMessageBox.Show(GetExceptionData(integrationException.Data, Constant.CmspMessageId));
                return;
            case (int)Enums.IntegrationSystemMessageDisplayType.CmspMessageWithIntegrationMessage:
                result = CustomMessageBox.Show(GetExceptionData(integrationException.Data, Constant.CmspMessageId),
                                             GetExceptionData(integrationException.Data, Constant.ErrorMessageNode));
                return;
            case (int)Enums.IntegrationSystemMessageDisplayType.CmspMessageWithIntegrationMessageAndCode:
                result = CustomMessageBox.Show(GetExceptionData(integrationException.Data, Constant.CmspMessageId),
                                             GetExceptionData(integrationException.Data, Constant.ErrorCodeNode),
                                             GetExceptionData(integrationException.Data, Constant.ErrorMessageNode));
                return;
            default:
                break;
        }
    }
    else //An unhandled exception like any other exception in the application
        throw ex;
}

10 Appendix

The codebase attached with this component will have the following items:

10.1 Database Components

A SQL Server 2008 database project, by name, ‘IntegrationSystemDb’ contains the following database components.

  1. Table Creation Scripts - CREATE table scripts for 3 tables, as mentioned in the data model are included
  2. DB Seed scripts – Scripts to add sample data for 3 tables, involved in the data model
  3. Stored procedures – A stored procedure being used by exception handler component, is included.

You can choose to deploy the database project to get the final deployment script.

10.2 WCF Service Components

The codebase contains a WCF Implementation project, WCFService. This folder in turn contains the source code for

  • Service Interface
  • It contains service, service contracts, service interceptors, data contracts, fault contracts, message contracts and service model. Web service software factory has been used to create service contracts.
  • Business Logic

    It contains business action classes that provide business logic execution.

  • Resource Access
  • It contains service agents to communicate with external systems

10.3 SOAP Exception Handler Component

It contains the component and the additional libraries. Common project holds all the common libraries and DataAccess project holds data entities.

10.4 External System Web Services

Two ASP.NET web service projects, ExternalSystemWS and ExternalSystem2WS, are included with the codebase to demonstrate how SOAP exceptions being thrown by these web services are handled using exception handler component.

10.5 Presentation Layer Components

It includes a windows form application for the user interface and Infrastructure.Wcf project to intercept WCF calls on the client-side. The sample windows form application demonstrates the usage of this component. This form application makes a WCF service call, which in turn consumes external system web services that throw SOAP fault exceptions.

In a typical distributed environment, the exception handler component will be part of Infrastructure services in the application server. The SOAP exceptions are caught at the WCF interceptor layer. The interceptor in turn invokes the exception handler component to handle such exceptions. Sample of how a WCF interceptor can invoke the exception handler component is detailed out in code samples.

In this sample windows application, the messages are stored in a resource file. The form application also includes additional services of a custom message box and a MessageUtil to process the messages from a resource file.

The class diagram of the sample windows form application is shown below:

Image 13

Figure 12 - Class diagram of User Interface

Summary

This article covers an approach towards handling SOAP exceptions, being thrown by external services in WCF based applications.  Thanks for reading the article. Please take time to post your comments/suggestions.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Infosys Technologies Ltd.
India India
Nandha Venkateswaran, Principal Technology Architect at Infosys, whose profession has rubbed onto her passion for technology which helped her in being innovative, collaborative, enthusiastic, agile to achieve great results

Comments and Discussions

 
GeneralMy vote of 5 Pin
User 76341407-Apr-15 3:00
User 76341407-Apr-15 3:00 
GeneralMy vote of 4 Pin
xphile725-Sep-13 3:28
xphile725-Sep-13 3:28 
GeneralRe: My vote of 4 Pin
Nandha V5-Sep-13 17:30
professionalNandha V5-Sep-13 17:30 

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.