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
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.1 | SOAP 1.2 | Description |
faultCode | Code | 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 | Reason | Required. A string explanation of the fault. |
faultactor | Role | Optional. URI describing source of fault |
detail | Detail | Optional. More information about the exception |
| Node | Optional. 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
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:
Layers | Description | Realization |
Presentation | Contains all presentation and user interfaces related aspects of the system as well as client side processing | WinFormApplicationInfrastructure.Wcf |
Application | Contains all the business logic and server side processes. | WCFService.ServiceContractsWCFService.MessageContractsWCFService.DataContracts WCFService.FaultContractsWCFService.ServiceImplementationWCFService.Service InterceptorWCFService.BusinessLogicServiceModel |
Domain | Contains all business domain entity objects. The objects are business model (domain) representation of the data | WCFService.BusinessEntities |
Resource Access | Contains all the components to access the relevant data store as well as external services | WCFService.ServiceAgentsDataAccess |
Data | Contains all the system data stores | IntegrationSystemDb |
Infrastructure | Contains all the framework components which provide the infrastructure services | WCFSoapFaultHandler |
Integration | Contains 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.
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
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.
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.
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.
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.
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.
Figure 9 - Data Layer
6 Data Model
The following diagram depicts the physical data model designed for this component.
Figure 10 - Data Model
3 tables are involved in this data model.
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.
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.
CmspMessageId
– A custom message Id that replaces the original exception message. Code
– Error code in SOAP fault to match with one or more specific exceptions. Match
– This parameter specifies, if the exception detail is to be matched with any of the following options
Exact
– one-to-one mapping between error code in SOAP fault and Code column in this table Range
– Code column in the table will contain a range of error code values (example: 25 to 72 expressed as ‘25_72’) 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.
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.
IntegrationMessage
- No translation of the error message in SOAP fault CmspMessage
– Error message in SOAP fault is completely replaced by custom message CmspMessageWithIntegrationMessage
– Partial translation of error message in SOAP fault such that custom message also contains original error message 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.
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:
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:
namespace WCFService.ServiceInterceptor
{
public class Bis2ServiceInspectorBehavior :
BehaviorExtensionElement, IEndpointBehavior, IClientMessageInspector
{
private const string ErrorCodeNode = "ErrorCode";
private const string ErrorMessageNode = "Message";
public override Type BehaviorType
{
get { return typeof(FileNetServiceInspectorBehavior); }
}
protected override object CreateBehavior()
{
return new FileNetServiceInspectorBehavior();
}
#region IEndpointBehavior Members
void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint,
System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
return;
}
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{ }
void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
{ }
#endregion
#region IClientMessageInspector Members
void IClientMessageInspector.AfterReceiveReply(
ref System.ServiceModel.Channels.Message reply, object correlationState)
{
if (reply.IsFault)
{
List<FaultDetailNodes> faultDetailNodesList = new List<FaultDetailNodes>();
faultDetailNodesList.Add(new FaultDetailNodes(ErrorMessageNode, false, 1));
faultDetailNodesList.Add(new FaultDetailNodes(ErrorCodeNode, true, 2));
MessageFault fault = MessageFault.CreateFault(reply, Int32.MaxValue);
FaultException faultException = new FaultException(fault);
IntegrationExceptionHandler.HandleSoapFault11(faultException,
Enums.IntegrationSystem.Bis2, faultDetailNodesList);
}
}
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:
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
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.
- Table Creation Scripts - CREATE table scripts for 3 tables, as mentioned in the data model are included
- DB Seed scripts – Scripts to add sample data for 3 tables, involved in the data model
- 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
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:
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