Category: Exception Handling


My current project requires an orchestration to be built that will call out to one or potentially many WCF Services through a sequential loop, the specific services to be called on within the loop being resolved from the Business Rules Engine based on message context. The orchestration needs to provide for guaranteed delivery and has retries built around the WCF Service calls in case of routing failures since the logical send port is of the direct binding type, or soap faults encountered when calling the WCF Service in question, or exhaustion of retries on the send port, or in case the  orchestration doesn’t hear back from the send port after a specified timeout period. The orchestration needs to perform as quickly as possible and use the minimum amount of machine resources since it is a high throughput orchestration which needs to process many millions of messages per day.

I managed to achieve the above using the below patterns.

My orchestration looked a bit like the below after implementing this logic (note that I have cut out a lot of my internal logic in this screenshot, there was a lot more to it but this gives you a jist of the flow).

Orchestration before

While running load tests it occurred to me that by catching timeouts the regular way with a long running transactional scope I was effectively forcing a persistence point every time the scope completed. To make things worse, my scope was nested within two parent scopes for error handling and variable scoping purposes and I was forced to mark both of these as long running too since you can’t nest a transactional scope within a non-transactional scope. If there were no orchestration shapes in between the ends of my three scopes then the persistence points would be collapsed into a single persistence point but my error handling really didn’t allow for this so I now had a minimum of three persistence points to deal with per orchestration instance, which my gut told me would definitely be causing performance issues and draining my server resources under heavy load thus constraining my throughput.

An alternative I decided to explore was using the listen shape with a receive branch to handle response messages and a delay branch to catch timeouts instead and to change all my scopes to be non-transactional (I wasn’t taking advantage of compensation so didn’t think I would lose any benefits of using a long running transactional scope).  However it looks like because I was using a logical request-response send shape in my orchestration this was not possible and I was encountering the error “incomplete requestresponse; missing receive” as described in this forum post whose poster was trying to achieve exactly the same ends.  It appears that the listen/delay timeout catching pattern does not work with request-response logical send ports in orchestrations.

When sending out a request-response message from my orchestration on a direct bound send port I noticed that my orchestration had an instance subscription to receive back the response messages based on the BTS.CorrelationToken context property.  This led me to believe that using a request-response logical send port in an orchestration automatically generates a GUID value in the BTS.CorrelationToken context property and promotes it, using that value to receive the response message back to the orchestration. physical send ports appear to automatically copy over the BTS.CorrelationToken promoted property from the request to the response or fault messages.  I decided to do the same thing except with a one-way logical port for the send and another one-way logical port for the receive and by manually promoting the BTS.CorrelationToken context property, thus enabling me to use the listen/delay timeout catching pattern.

I created a one-way logical send port instead replacing my request-response send port and also created a new one-way receive port with an operation with a message matching the response message from the send port.  When constructing the request message I created a new GUID and set it’s value to the BTS.CorrelationToken context property on the message.  I created a correlation type containing the BTS.CorrelationToken context property, created a correlation set of the aforementioned type in my innermost scope which I initialized on my send shape and followed on my receive shape to force the property to be promoted.  I then created a listen shape and moved my receive into the first branch, and created a delay shape in the second branch to catch timeouts and put my timeout exception handling logic in that branch.  I could now safely mark all my scopes as non-transactional and my orchestration looked like the below.

Async Timeouts1

Load testing immediately garnered better results, with my transactions per second on a previously base-lined application rising from 78 to 90 (a 15% increase in throughput) and the CPU utilization on my message box SQL Server dropping massively.  I instantly felt vindicated that the extra effort had paid off, but then realized that I had lost out on my ability to catch SOAP faults and messages indicating retries on my send port had exhausted which was not acceptable.

To catch SOAP faults I had to add a new operation to my one-way receive port with a message type of BTS.soap_envelope_1__2.Fault, add a new branch to my listen shape in which I put a receive shape for a message of the same SOAP fault type and linked it to the new operation on the receive port, and also had this receive shape follow the same correlation set that I initialized on the send.  I could then run XPath statements against the soap fault message to extract the exception details and handle it accordingly. Since send ports copy over the BTS.CorrelationToken context property to all response messages including fault messages this wasn’t too hard to do.

The failed messages on send ports that had exhausted retries were a bit trickier to deal with.  This is because I could not find any clean way (there was one method which could work as described in this blog post but I really wanted to avoid having to receive back the original request message into my orchestration instance to support this pattern as that would add inefficiencies and affect throughput) to correlate these failed messages back to my orchestration as the failed messages were of the same message type as the original request message except they now had some error context properties.

I decided to take advantage of NACK (negative acknowledgment) messages instead (see this blog series if you want more information about generating NACKs on send ports).  NACK messages are simply messages of type BTS.soap_envelope_1__1.Fault however do not have a BTS.MessageType context property set against them.  They are also only generated by send ports upon retry exhaustion if there is an existing subscription for the NACK (or if you use the orchestration delivery notification functionality or BTS.ACKRequired context property but those weren’t suitable for my purposes).

I decided to use a loopback send port (the loopback adapter in question being developed by my friend and colleague Mark Brimble and is proprietary so can’t be shared, though you can find other implementations on the internet) to subscribe to NACKs off the WCF service send ports as well with an XMLReceive receive pipeline to resolve the message type of the NACK since they don’t have a BTS.MessageType context property by default.  An orchestration could have been used instead of a loopback send port however that means i would not be able to adjust the filter properties at runtime which wasn’t flexible enough for my purposes. See an example of filter properties on the loopback send port to have my WCF service send port generate NACKs.

Loopback

I then added another operation to my logical one-way receive port in my orchestration with a message type of BTS.soap_envelope_1__1.Fault, added a new branch to my listen shape with a receive shape for a message of type BTS.soap_envelope_1__1.Fault linked to the aforementioned operation which also followed the correlation set initialized on the send of the WCF Service request message.  I could then run XPath statements against the received NACK message to extract fault details and handle the exception appropriately.  The orchestration now looks like the below.

FullyImplemented

The one catch now is that I need to discard the failed messages that get generated as a result of the “routing for failed messages” flag being enabled on the send ports (I still need this enabled because my solution calls for error handling to be done from within the orchestration for this specific message flow rather than from send ports for guaranteed delivery purposes, and I want to ensure that send port instances do not remain suspended after retries get exhausted) as they will be created in addition to NACKs.  This does result in extra unnecessary messaging when retry exhaustion occurs, but this is expected to be the exception rather than the norm and was deemed acceptable for this solution. The same justification applies for the addition of the loopback send port.

Something else to keep in mind is that if the Web Service you’re calling is not a WSHttp binding (or equivalent WS* based) based Web Service then the fault you will need to catch will most likely be of type BTS.soap_envelope_1__1.Fault which is the same type as NACK messages.  In this case you would have to consolidate the listen branch for the SOAP fault and NACKs into a single branch and inspect the message to find out if it is a SOAP fault or a NACK before dealing with it appropriately.

There is no question that this solution is more complicated than using a request-response logical send port in your orchestration in combination with a long running transaction scope to catch timeouts, and adds more components for future developers to wrap their heads around as well as making life more complicated for support people.  However if throughput is of the utmost importance to you and every message per second processed by your BizTalk application makes a world of a difference, then this might just be the solution you need.

Advertisements

Welcome back to the “Throwing typed WCF faults back to consumers in a BizTalk messaging only application” blog series.  This is the 6th and final (hopefully) part in the series and aims to describe the improvements in the client experience as a result of applying the solution described throughout this blog series, and to conclude the series.  If you haven’t yet read the prior entries in this series then follow the below links before you continue reading this entry.

Part 1 : Introduction

Part 2: Creating the typed fault

Part 3 : Publishing the typed fault contract in the WSDL

Part 4 : Creating a custom error handling service behavior

Part 5 : Creating an endpoint behavior to copy headers and the SOAP action from the request to the response

To quickly summarize what has been covered in this series, in the second post we created a custom serializable class which is decorated with DataContract/DataMember attributes and represents our custom typed fault but doesn’t derive from System.Exception.  We have also created the schema representation of the fault class and deployed it to the BizTalk runtime.  In the third post we made use of a slight variation of the WsdlExtensions endpoint behavior to extend our WSDL such that it published the metadata for the typed fault and associated it as a fault message on operations described in the WSDL.  In the fourth post we implemented a custom service behavior that enlists a custom error hander that intercepts the out of the box BizTalk pipeline exceptions and replaced them with the custom typed fault, populating the fault elements with sanitized fault details, and setting a hardcoded SOAP action on the response message (which would be a problem for programmatic clients if this was not overridden).  In the fifth post we implemented a custom endpoint behavior which enlists a custom message inspector that copies over the soap action as well as a specific SOAP header from the request message to the response, thus fixing the issue with the wrong SOAP action being associated with fault messages as well as making life easier for BizTalk service consumers.

The remainder of this post will summarize the client experience for .NET and BizTalk consumers of a BizTalk hosted WCF service that makes use of these solutions.

.NET clients

.NET clients need simply add a service reference pointing to the WSDL associated with the service in question to generate all the proxy classes required to call on the service and consume exceptions.   Calls to operations exposed by the service reference should be surrounded by try catch blocks, specifically catching an exception of type System.ServiceModel.FaultException<CustomException> where custom exception is the typed fault class generated by the service reference.  Once within the catch block, you can access the elements contained within the typed fault by inspecting the Details property of the exception object.  We have managed to make life much easier for .NET consumers of our service and as far as they are concerned they shouldn’t even be aware that they are connecting to a BizTalk hosted service.

DotNetSummary

BizTalk clients

BizTalk clients have a relatively similar experience as well with a few additional challenges to overcome.  Running the “Add generated items/Consume WCF Service” wizard against the WSDL results in schemas being created for all the operations contained within the service as well as the typed fault schema.  What is also interesting is that the orchestration file that gets generated also correctly creates a port type representing operations contained within the service with the correct typed fault as well.

AutomaticallyGeneratedPortType

The client now has the option of copying over the identifier value to an outbound header which ensures that it is also included in the response message.  One way in which I would look at populating the outbound header would be to promote the element within my message body that relates to the identifier to a context property and then use the BRE Pipeline Framework on the send port’s send pipeline to copy that context property value to the WCF.OutboundCustomHeaders context property.   This can be achieved by using string concatenate, get context property and set context property vocabulary definitions provided for in the BRE Pipeline Framework to set the value of the WCF.OutboundCustomHeaders context property in the following format – <headers><s:CustomHeaderName xmlns:s=”urn:customheaderns”>ContextPropertyValue</s:CustomHeaderName> </headers>.  This results in the header being copied onto the response message and being converted into a context property with a name and namespace matching those of the header in the request message as below.  This context property could be accessed in a pipeline or an orchestration, or in combination with the context accessor functoid it could even be accessed in a map.

BizTalkResponseContext Take 2

There is another challenge encountered in my scenario as the service is hosted by a one-way receive location thus returns a blank or void response.  In order to consume the typed fault returned by the service, the BizTalk send port used to consume the service would need to be created as a Solicit-Response send port rather than a One-way send port, the propagate fault message option in the message tab needs to be enabled, routing for failed error should be disabled to ensure that transport exceptions result in retries and suspension of the messaging instance rather than the messaging instance being terminated and routed to the error handler (I recommend that NACKs are used to escalate these transmission failures to the appropriate exception hander, see this blog series of mine for more details on NACKs), and the receive pipeline on the send port should be set to one that makes use of an XML Disassembler pipeline component so as to resolve the message type on the response message so that it can be run through maps or routed based on message type.

The challenge is that while the XML Disassembler pipeline component can correctly resolve the SOAP fault message, it can’t really resolve the message type on successful responses since the body of the message is empty.  I would recommend looking at the BizTalk 2006 Create Body Part pipeline component for inspiration on creating a body part when the body part is empty, or to otherwise look at doing the same through a custom WCF behavior, most likely through the use of a message inspector.

The fault message received by BizTalk looks like the below and the typed fault elements and the custom header values can be accessed and manipulated as desired.

Formatted XMLVAL xml

Conclusion

A lot of the solutions I have discussed could be made more dynamic and I welcome suggestions and feedback.  For example the custom error handler could be made to use an external config store such as the BRE or the SSO for mappings of out of the box exceptions to custom exceptions rather than hardcoding them into the error handler, or the message inspector could also similarly be made to use an external config store to lookup which headers get copied from the request to response.  The solution could also be extended further to cater for multiple typed faults, etc…  I’m sure there are many ways to implement the solution I have described, possibly in an easier fashion (not that I know of though), and I would be very keen to hear your thoughts.

I hope that you have taken something away from this blog series, and at the very least the content discussed makes you ask a few more questions about how you are going to deal with exceptions the next time you approach a BizTalk project that relies on WCF.

Welcome back to the “Throwing typed WCF faults back to consumers in a BizTalk messaging only application” blog series.  This is the 5th part in the series and specifically focuses on copying custom headers from the request message to the response message to aid BizTalk (or other messaging engine) service consumers by ensuring the response message contains enough context that it can be handled independently from the original request, and it also deals with copying over the SOAP action from the request message to the fault message to ensure that .NET (and other programmatic frameworks) consumers can properly consume typed fault messages.  If you haven’t yet read the prior entries in this series then follow the below links before you continue reading this entry.

Part 1 : Introduction

Part 2: Creating the typed fault

Part 3 : Publishing the typed fault contract in the WSDL

Part 4 : Creating a custom error handling service behavior

The previous entry in this blog series highlighted how the correct SOAP action must be attached to the generated typed fault message before it is sent back to a .NET consumer or it will not be able to catch the typed fault and will instead only see a generic System.ServiceModel.FaultException exception which doesn’t contain all the exception detail of interest.  In order to get around this issue we must ensure that we copy the SOAP action from the original request message to the response message and I have achieved this via an endpoint behavior.  It should be noted that endpoint behaviors always execute after service behaviors, thus this endpoint behavior would override the hardcoded SOAP action that was set on the fault in the service behavior built in the fourth part of this blog series.

The first entry in this blog series also highlighted that if a BizTalk consumer of the service in question wanted to build a messaging only application, they would find that the fault message would not contain enough information in it for an operations staff to deal with it if it were routed to an exception handling mechanism, since it doesn’t contain any identifying elements, and thus an orchestration or some other mechanism would need to be created to inject values from the request message into the exception before it was passed to the exception handler.  It would be ideal if the service catered for a mechanism to optionally copy over context from the request message to the response message and I decided that the context would be contained within a custom SOAP header which would also be copied over by an endpoint behavior.

I decided to kill two birds with one stone and solve both these problems with a single endpoint behavior which makes use of a custom message inspector which copies over headers from the request to the response.  There is no reason why these couldn’t be split out into two separate behaviors altogether or at least two separate message inspectors.

This message inspector uses the WS-Addressing MessageID and RelatesTo headers to form a correlation token to link a request message to a response message, adding the MessageID to a dictionary (note that you should assess how best to clear out your caches to ensure you don’t encounter a memory leak) as a key with the values being made up of headers that I wanted to persist for the current message.    The AfterReceiveRequest method of the message inspector which persists the headers to be copied over looks like the below.  Note that if a MessageID is not provided by the client then one is made up and applied to the RelatesTo header to ensure that request and response correlation is possible in the message inspector.

AfterReceiveRequest

The BeforeSendReply method which populates headers (including the SOAP action) on the reply message from the appropriate cached instance using the RelatesTo header on the reply message as a correlation token looks like the below.

BeforeSendReply

In order to enlist this message inspector you must create an endpoint behavior as below.

PropertiesBehavior

And in order to bind the endpoint behavior you must create a behavior extension element class as below, which is very simple since our endpoint behavior doesn’t expose any parameters.

PropertiesBehaviorExtensionElement

You will now need to build your endpoint behavior project, register it in the GAC, and register it in your machine.config files.  As stated in part three of this blog series, my colleague Shadab has written a blog post on using WIX installers to install custom behaviors which includes registering them in the required machine.config so that is worth a read if you want more details on this.

You can now add this endpoint behavior to your BizTalk WCF-Custom or WCF-CustomIsolated receive location.  On the behaviors section of the adapter configuration you should now be able to right click on EndpointBehavior, choose add extension and select the behavior name that you bound your extension element class to in the machine.config.  If you don’t see it in the list then either your code has some problems in it, you haven’t registered the assembly in the GAC correctly, you haven’t registered the behavior in your machine.config files correctly, or you haven’t restarted the BizTalk Administration Console after doing the aforementioned tasks.

The result of this is .NET consumers of the service are now able to catch the typed faults and access contained elements as illustrated in the below screenshot.  This is purely a result of the message inspector copying the SOAP Action from the request message to the response message.

DotNetTypedFault

To illustrate this a bit better, take a look at the below request message sent to the service from SOAPUI.  Note the Identifier custom header included in the message.

Request

The result of this is that it will be copied over to the response as well as below.  Note that if the request did not contain the Identifier header then it would not be included in the response.  If a MessageID was not sent with the request (this can be controlled via the WS-A tab in SOAPUI) then the RelatesTo header would not be included in the response.

ResponseWithRelatesTo

I will discuss the usage of the custom headers by BizTalk a bit more in the next entry in this blog series in which I will describe how the client experience has been improved through the usage of the solutions described in this blog series.

If you are interested in reading further then do follow the links to further entries in this blog series.

Part 6 : The client experience

Welcome back to the “Throwing typed WCF faults back to consumers in a BizTalk messaging only application” blog series.  This is the 4th part in the series and specifically focuses on creating a service behavior that enlists a custom error handler that inspects out of the box exceptions thrown by BizTalk pipelines and replaces them with the custom exception that was created in the second part of this series.  If you haven’t yet read the prior entries in this series then follow the below links before you continue reading this entry.

Part 1 : Introduction

Part 2: Creating the typed fault

Part 3 : Publishing the typed fault contract in the WSDL

In order to intercept out of the box BizTalk pipeline exceptions and replace them with our custom typed fault we must create a class which implements the System.ServiceModel.Dispatcher.IErrorHandler interface as below.

ErrorHandler

In the above error handler class a ProvideFault method is created which has access to the out of the box generated exception.  This exception is inspected and the reason, message, and faultCode variables have values set based on evaluation of the exception.  For example if the exception message contains the string “Source: “”XML validator””” then we can derive that the exception is an XML validation fault so we can set the faultCode to XMLVAL, the reason to XML Schema Validation Failure, and we can set the message to a sanitized version of the original exception’s message, stripping out any unnecessary details.

We then use these variables to instantiate an instance of a System.ServiceModel.FaultException object of the type of our custom typed fault, passing in a new instance of our typed fault using the aforementioned variables to populate it’s elements into the constructor of the FaultException.  We then instantiate a System.ServiceModel.Channels.MessageFault object with the help of our FaultException object, and then populate the fault message which is of type System.ServiceModel.Channels.Message, and was passed into the method by reference, with the MessageFault object.

When we populate the Message object we must also specify a SOAP Action, however as you might have noted in the third part of this series when you generate proxy code from the WSDL the action against the FaultContract is the same as that of the request message rather than * which allows for any action.  This means that hardcoding a SOAP action is going to cause problems for the client so we really need to populate it with the action value from the original request that was received by the service, but I have not quite found a way to do this in a service behavior.  For now we will just populate the action with a hard coded value and I will show you how to fix this up in an endpoint behavior in the fifth part of this blog series.

Next up we must create a service behavior that will enlist our custom error handler class as below.

ErrorHandlerServiceBehavior

Finally we need to create a behavior extension element class that binds our service behavior, which is very simple since our service behavior doesn’t expose any parameters, as below.

ErrorHandlerBehaviorExtensionElementTake2

You will now need to build your service behavior project, register it in the GAC, and register it in your machine.config files.  As stated in part three of this blog series, my colleague Shadab has written a blog post on using WIX installers to install custom behaviors which includes registering them in the required machine.config so that is worth a read if you want more details on this.

You can now add this service behavior to your BizTalk WCF-Custom or WCF-CustomIsolated receive location.  On the behaviors section of the adapter configuration you should now be able to right click on ServiceBehavior, choose add extension and select the behavior name that you bound your extension element class to in the machine.config.  If you don’t see it in the list then either your code has some problems in it, you haven’t registered the assembly in the GAC correctly, you haven’t registered the behavior in your machine.config files correctly, or you haven’t restarted the BizTalk Administration Console after doing the aforementioned tasks.

The result of this is that the behavior will now intercept your out of the box exceptions and will replace them with your custom exceptions.  A BizTalk consumer of the service is now able to receive fault response messages and you can route them to the appropriate error handler (though you will need to use XSLT in your maps if you want to access any of the values in the Detail node of the message, as according to the Fault schema, Detail is an xs:any node).  An example fault message looks like the below.

Formatted XMLVAL xml

However this is not the end of the story since .NET clients are frustratingly still not able to catch the typed fault due to the incorrect SOAP action being set against the fault.  This can be illustrated quite easily in the below screenshot in which the above exception is returned to a .NET client however because of the incorrect SOAP action the typed exception handler is bypassed and a more generic System.ServiceModel.FaultException exception is caught.  If you inspect the exception you will see that all the element values that were contained in the XML representation of the typed fault in the above screenshot have been lost as the .NET serializer did not know how to deserialize the XML and thus threw those element away.  This problem will be addressed in the fifth part of this blog series.

DotNetGenericFault

If you are interested in reading further then do follow the links to further entries in this blog series.

Part 5 : Creating an endpoint behavior to copy headers and the SOAP action from the request to the response

Part 6 : The client experience

Welcome back to the “Throwing typed WCF faults back to consumers in a BizTalk messaging only application” blog series.  This is the 3rd part in the series and specifically focuses on how you can publish your typed fault contract in your BizTalk WCF service’s WSDL.  If you haven’t yet read the prior entries in this series then follow the below links before you continue reading this entry.

Part 1 : Introduction

Part 2: Creating the typed fault

This part has largely been figured out by Paolo Salvatori in this fantastic blog post which proves it’s relevance many years later.  To a large degree I have used Paolo’s WsdlExportExtenions endpoint behavior code as is.  The one major exception to this is that I had to modify his AddImportedSchemas method in the Microsoft.BizTalk.CAT.Samples.PublishTypedFaults.WsdlExportExtensions.WsdlExportEndpointBehavior class in the WsdlExportExtensions project.  The reason for this is that it contains a foreach loop which iterates through each XmlSchemaImport object in schema.Includes, however you will find that this falls over if one of your schema in the WSDL makes an includes reference to another schema (i.e. they both belong to the same namespace) rather than just imports references which this behavior already works perfectly for.  The fix for this appeared to be to iterate over each XmlSchemaExternal object in schema.Includes instead, XmlSchemaExternal being the base class from which XmlSchemaImport is derives from.  The method now looks like the below.

AddImportedSchemasMethod

Once this was done the next step was to build the WsdlExportExtensions project, register it in the GAC, and register it in both the 32-bit and 64-bit machine config files.  My colleague Shadab has written a blog post on using WIX installers to install custom behaviors which includes registering them in the required machine.config so that is worth a read if you want more details on this.

Now the next step requires you to inspect your WSDL and plan out how you will associate your typed fault as a fault message on your given operations.  In the below screenshot you see that I have focused on the portType section of the WSDL very specifically, and what you need to take note of is the portType name, the name of any contained operations (in this example there is only one operation but you might have many if your service contains multiple operations)

WSDLPortPrior

The next thing you will want to do is to prepare the XML configuration you will need to feed into the WsdlExtensions property of the service behavior which is used to inject elements into your WSDL.  You can copy the example XML from Paolo’s blog post (search for “WsdlExtensions property” on the page).

WsdlExtensions config

There are a few important sections in this XML.

  • The first important thing is to declare a namespace prefix.  The choice of value isn’t really significant except you probably want to avoid clashes with default namespace prefixes so I suggest you be creative in your choice.
  • Next up we need to declare the name (equivalent to the root node of your schema) and namespace of the schema which we have deployed to the BizTalk runtime that represents our custom exception in the XmlSchema node.
  • Next we need to create a WSDL message that represents our custom exception message in the Message node.  To do this we need to assign the message with a name which is rather arbitrary except that you will want to avoid clashes with other message names.  You will want to specify the namespace of your schema, and then in the part node specify the root node name of your schema in the element node and give the part a name which is rather arbitrary, and I don’t believe you need to worry about clashes unless you are creating a multi-part message which we aren’t.
  • Next up we need to associate our exception message with a given operation on a given port type.  To do this we specify the name of the port type from the WSDL in the PortType/Name element, and the name of the operation from our WSDL in the PortType/Operations/Operation element.  In the PortType/Operations/Faults/Fault node we then specify a name for our exception which is rather arbitrary from a runtime perspective but best to choose an appropriate name, and then specify the name of the message that we declared in our previous step.

Once the XML is prepared then we need to remove all line breaks from it so that it can be pasted into the WsdlExtensions property of the service behavior.  I personally use the Remove Line Breaks Online Tool to help me do this.

In order to make use of the service behavior it is very important that our receive location uses either the WCF-CustomIsolated (if to be hosted by IIS or another isolated host) or WCF-Custom (if to be hosted by an in-process host) adapter, as adapters such as WCF-WSHttp or WCF-BasicHttp can not enlist the use of WCF behaviors (I’m not sure if you can manually adjust the web.config files for these adapters to bind behaviors to the service but I would suggest that this is avoided even if possible).  On the behaviors section of the adapter configuration you should now be able to right click on EndpointBehavior, choose add extension and select the wsdlExport behavior.  If you don’t see it in the list then either your code has some problems in it, you haven’t registered the assembly in the GAC correctly, you haven’t registered the behavior in your machine.config files correctly, or you haven’t restarted the BizTalk Administration Console after doing the aforementioned tasks.  Once you have selected the wsdlExport behavior you can paste in the flattened XML configuration into the WsdlExtensions property.

WsdlExtensionsBehaviorBTS

This endpoint behavior will adjust the WSDL in the below ways.

  • The WSDL has now been flattened, which means that schemas are no longer contained in separate XSD files referenced from the WSDL, but rather are defined within the WSDL itself.
  • The custom exception schema is now contained within the WSDL so will be generated in proxy code if you add a service reference within your client application to the service.
  • There is now a message which contains a part of the custom exception type, and this message is associated with the operation we extended in the XML configuration for the endpoint behavior as a fault message.

WSDLPortPost

If you generate a service reference off this new WSDL and you inspect the OperationContract generated you will notice that the operation is now decorated with a FaultContractAttribute which specifies a type of our custom exception.  In theory now we can surround our calls to this specific operation with a try/catch block in which we catch an exception of type System.ServiceModel.FaultException<CustomException> where CustomException is the typed fault class generated as part of the service reference.

ServiceReferenceOperationContract

Also take note of the fact that the action specified against the FaultContract is the same as that on the request.  This is not consistent with the response which has an action of * which implies that any action will be accepted.  This has some further implications that we will explore further in the fourth part of this blog series.

If you are interested in reading further then do follow the links to further entries in this blog series.

Part 4 : Creating a custom error handling service behavior

Part 5 : Creating an endpoint behavior to copy headers and the SOAP action from the request to the response

Part 6 : The client experience

%d bloggers like this: