BizTalk Utilities CV ,   Jobs ,   Code library
 
Home Page


Add/Edit your code items
Search the code library
Browse for the code library


WCF, WS, SOAP
Accessing UDDI using Apache Scout APIs
Storing state in an XML property bag
UDDIExplorer
XslTransport for PocketSOAP
Kafka - XSLT SOAP Toolkit
VB Web services Proxy Generator
Using msxml3 with Web Storage System
Getting started with SOAP
Calling an Web service from a Managed C++ project
How to access asyncronously from C# an web service
What is XML-RPC?
Web Service and DHTML
Use XMLDOM and XMLHTTP Documents to Upload Small Files
Temperature Conversion XML WebService
SOAP Client Over HTTP Using Visual C++
SOAP Toolset for VB 6.0
Remote Database Administer via XMLHTTP
Binding XML Data Island to Web Forms
Security Model for Web Services
What is a XML Web Service?


 
 

<< UncategorizedXALAN >>


By Richard Seroter
First Posted 01/31/2008
Times viewed 24987

BizTalk and WCF: Part I, Operation Patterns


This series of articles on WCF/BizTalk Server 2006 R2 integration will touch upon many aspects of connecting these two critical technologies together in a rich and interesting way. First and foremost, let’s take a look at some of the most common scenarios where BizTalk consumes a WCF service. Before I can dig into topics such as security, binary data processing and transactions, we need to lay a solid foundation with the base use cases.

The article covers the following scenarios:

Caller

Input Type

Output Type

Fault

Orchestration Complex Type Complex Type n/a
Orchestration Complex Type Complex Type Custom Fault Contract
Orchestration Simple Type Simple Type n/a
Orchestration Simple Type Simple Type Unknown Fault
Orchestration Simple Type None n/a
Messaging Simple Type None n/a

In this article I will show you how to call WCF services from BizTalk in a variety of ways, handle faults, and trace your output.


Service Setup


Let’s first review the WCF web service that BizTalk Server will call. The data contract used by the service defines a Patient object.

I’ve defined one more data contract which specifies a custom service fault type.

Ok, now that the data definitions have been defined, let’s look at the service contract itself.

I’ve defined three operation contracts in my interface. One, RegisterPatient, accepts and returns a complex type, while also returning a specific fault contract for exceptions. Next I have QueryPatientStatus which accepts a simple type (string) and also returns a simple type. Finally, ModifyPatient accepts a complex type, but returns nothing.

You’ll notice that I have a fourth operation commented out. I used this to test BizTalk behavior with “one-way” services, and saw the behavior mentioned in the documentation (WCF adapters do not support one-way operations). From my WinForm WCF test client this operation works fine (hence I kept it there for testing purposes), but left it commented out for BizTalk usage. If I did NOT leave this commented out, the BizTalk WCF Service Consuming Wizard would not successfully complete. (The BizTalk WCF Service Consuming Wizard does not allow the combination of one-way and request-response operations).

The RegisterPatient operation has a specific fault contract (OperationExampleFault) which you can see utilized here in my operation implementation.

If the new patient is in the “Pacific Northwest” region, I instantiate and throw an OperationExampleFault message. The ModifyPatient operation also throws exceptions, but in that case, I used the more generic “throw new FaultException("Bad patient ID supplied");” command.

The next step was to build a host container (in my case, a self hosted WinForm application) which manages this service lifecycle. My host configuration file identified a behavior which enables service metadata () and used an HTTP endpoint (http://localhost:8880/OperationService).


BizTalk Setup


In order for this next stage to work, I needed to actually start up my WCF service host. Now BizTalk can interrogate this service to extract the necessary metadata. Within Visual Studio.NET, I chose “Consume WCF Service” from the “Add Generated Items” project menu. Note that this is different than the “Add Service Reference” project option available when referencing WCF services in other .NET project types.

I could generate the metadata files explicitly via the WCF svcutil.exe function (e.g. svcutil /t:metadata http://localhost:8880/OperationService?WSDL) , but instead, I chose the first option, which more closely resembles the Add Web Reference walkthrough you’re probably familiar with. If the service host is up and running and a valid URI is entered, then the corresponding WSDL is returned.

Upon completion of the wizard, a series of files are added to the BizTalk project. (Note: you don’t HAVE to use this wizard if you don’t like all the files generated, but for simplicity sake, let’s stick with it). For me these files include:

  • PatientService_tempuri_org.xsd – Contains all the operation contracts (e.g. RegisterPatient, RegisterPatientResponse)
  • PatientService_act_org_2004_07_Seroter_BizTalkWCFTutorials_OperationExample.xsd – Holds the contract definition of both “Patient” and the custom fault.
  • PatientService_schemas_microsoft_com_2003_10_Serialization.xsd – Contains all the base XSD types (I exclude this file from my solution, to no ill effect).
  • PatientService.odx – Holds the multi-part message types and port types for calling the WCF service.
  • PatientService.BindingInfo.xml – A binding file for the send port which uses the transport (e.g. TCP, WsHTTP, etc) identified.
  • PatientService_Custom.BindingInfo.xml – Another binding file for the “WCF-custom” adapter which surfaces many more WCF properties you may want to use.

My next step was to actually create an orchestration that called the WCF service. I didn’t use the auto-generated PatientService.odx orchestration because I didn’t want to be forced to redo work if I regenerated my solution bits later on. So, I created another orchestration which simply uses the types identified in the auto-generated orchestration.

The first thing to do in my new orchestration was to create messages. Unlike with the SOAP adapter, I didn’t point to “web messages.” Instead, I point to the multi-part messages created by the wizard.

Note that EVERY WCF parameter, whether complex OR simple type is represented as a schema type. Unlike with the SOAP adapter and simple type parameters, the WCF simple type messages must be created the same ways that a complex message is created (e.g. map). For the SOAP adapter, the simple types did not show up in the generated schema, but as you can see here, there is a complex type created for my simple string input parameter.

Notice that you can, however, distinguish any of these fields to access input/output values. Above, you can see that I distinguished the QueryPatientStatusResult element (of type string) so that I could quickly read the response value.

My orchestration is set up to call each of my three WCF services in sequence.

In each case, I used a BizTalk map to instantiate the “request” message for the service. And for each scenario, I published a trace message upon successful completion of the call. Note that even though ModifyPatient returns “void”, there is still a BizTalk message that is associated with it. This message has no content, but you have to specify the message variable and connect it to the port nonetheless. For the WCF service calls that DO return a result, I used a distinguished field to yank that value and throw it into my trace log.


Deploy and Test


The project was now ready to build and deploy. Upon successful deployment, I created a receive port/location to absorb the “starter” message which triggers the orchestration. For the send port, I chose to “import … bindings” and pointed to each of the binding files generated by the BizTalk WCF Service Consuming Wizard.

Notice that I have two ports (corresponding to the two binding files that get auto-generated by the BizTalk wizard).  One uses the WCF-WSHttp adapter, and the other uses the WCF-Custom adapter.  The WCF-Custom adapter is using the WSHttp binding, but, the adapter surfaces more configuration settings than the plain WCF-WSHttp adapter.

The service endpoint is displayed on the “General” tab of the WCF-WSHttp adapter configuration.

Notice that we have three “actions” identified because all three WCF service calls from the orchestration use this same port. Based on the operation name in the orchestration, the appropriate “action” is used.

After first binding my orchestration to this generated WCF-WSHttp port, and starting the application, I dropped my trigger message into the folder polled by the receive location. I could monitor my progress by using the DebugView tool (http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx). I should see statements printed by both the WCF service, and the orchestration itself if a successful response is received.

So I could see success all around. Now let’s say that I wished to actually watch the payloads travel across the wire. With the WCF-WSHttp adapter configuration I can’t enable that behavior. However, if I used the auto-generated WCF-Custom send port, I have much more control of my WCF client (i.e. BizTalk Server). Specifically, I want my good friend TCPTrace (http://www.pocketsoap.com/tcptrace/) to watch the raw XML travel back and forth. However, I can’t simply switch my URL to point to the TCPTrace listener as I’ll end up with service addressing errors. However, I CAN use the WCF “clientVia” behavior configuration to enable the service to properly accept forwarded traffic. On the “Behaviors” tab of the WCF-Custom adapter configuration, I chose to add an extension, and selected “clientVia.”

In the “viaUrl” property of that behavior extension I set the Url to be http://localhost:8800/OperationService. This is a different port (8880 vs. 8800) than my actual service endpoint is listening on. Once I start up TCPTrace, I chose to listen on port 8800 and forward traffic to 8880.

After switching my orchestration binding to use this other send port, and dropping my “trigger” message, I can now see the raw XML transmission.

This is a great way to debug or observe the pure XML object before it gets serialized to an object.


Handling Exceptions


So what about that fancy Fault Contract I created at the beginning? Where does that come into play? Because my WCF service operation was decorated with the FaultContract attribute, the fault schema was generated, and my port for the RegisterPatient operation has an available fault message.

How do I use this? My call to RegisterPatient was wrapped in a non-transactional scope with an exception handler defined. If I looked at the available “Exception Object Types”, I could see that there’s a new exception type matching my custom fault.

Neat. So, I simply choose that exception type, and, assuming an “Exception Object Name” of faultEx, the following code in my exception handling block works perfectly:

//ErrorMessage is the name of the property in my custom fault contract

System.Diagnostics.Trace.WriteLine("Orchestration failed calling two way (complex) service. Error: " + faultEx.detail.ErrorMessage);

Almost done. After redeploying this solution, I had to change my send port. Why? Because right now, my send port “Messages” tab is configured to take the WCF service result message, and yank out the “body” from the SOAP envelope.

Why is this bad? Because our fault message is based on a root node of OperationExampleFault and this bit of XML is buried a few layers down within the fault message returned by the service. If we leave this “Body” setting on the port, we’ll get an orchestration “mismatch” error because we’re trying to serialize the whole fault message into the expected OperationExampleFault type.

How do we handle this situation? By using the “Body path expression” feature of the port! Now, you may ask yourself (as I did), why do I want to specify an XPath targeting the fault message, when most of the time a fault is NOT being returned by the service? What happens when I get my regular, “good” result? The key is how you write the Xpath expression. By utilizing a Xpath “union” command (the “|” token), you can include all possible result values, and whichever matches the service response gets used. In my case, the “Body path expression” is:

/*[local-name()='Fault']/*[local-name()='Detail']/* | /*[local-name()='RegisterPatientResponse'] | /*[local-name()='QueryPatientStatusResponse'] | /*[local-name()='ModifyPatientResponse']

Here I have a union of node sets, and per the documentation, the first match is used. So, if I have a fault, then the OperationExampleFault node will be pulled from the /Fault/Detail path, and if there is no fault, the appropriate successful response value is returned to the orchestration. This can be a tricky concept, so I encourage you to play around with this.

What happens when I triggered an exception? Via TCPTrace I could see the raw fault XML.

Notice the OperationExampleFault node nested within the Fault container. If I reviewed the DebugView, I saw that the orchestration caught the custom fault, and printed out the value stored in the ErrorMessage property.


Performing "Messaging Only" WCF Service Call


The final “calling WCF services” scenario centers on calling a service without using an orchestration. This was a feature of the SOAP adapter introduced in BizTalk Server 2006, and still remains with the WCF adapter.

Let’s assume that I have walked through the BizTalk WCF Service Consuming Wizard and have all my schemas. One benefit of having simple type parameter still require a BizTalk schema type is that you can now call simple type parameter services without an orchestration. Using the SOAP adapter, you have no easy way of instantiating simple types (without a custom pipeline or orchestration) and can only easily call services with complex (schema) types. In my case, I want to call my ModifyPatient operation (which accepts a string value and returns void) using only the BizTalk messaging layer. How do I do this? Easily. I first created a new receive port/location to absorb my trigger message. Then, I created a static one-way send port. I have nothing waiting for a response message, so I don’t want to create a solicit-response port. My new send port uses the same endpoint Url (http://localhost:8880/OperationService) as my auto-generated port(s). After adding a send port filter subscribing to messages from my new receive port, I added the final, crucial step. I have to add an outbound map to take my trigger message and create the ModifyPatient request message for the adapter. Once all that is in place, I could drop a file into my directory polled by my new receive location, and watch my service get called.

Sure enough, my service was called successfully from the BizTalk messaging layer. What if I trigger an exception now? Even though this is a “one way” service via the “void” response type, this service still behaves in a synchronous fashion. We get a passive acknowledgement that the service completed with no errors, hence why we have an empty response message auto-generated for this service. So, any fault raised in this pseudo-one-way service gets bubbled up. In this case, the exception is returned and we get a suspended message inside BizTalk Server.

 

 


Summary


So what have we seen here? I’ve shown you how to call WCF services in a variety of ways (complex vs. simple types, one-way vs. request-response, orchestration vs. messaging) and use the wizard-generated components to significantly speed up development. We also looked at some tricks to enable deeper tracing via TCPTrace, as well as supporting custom Fault contracts inside an orchestration.

My next article will explain each of the WCF security configurations that are supported from BizTalk Server.

Once this entire BizTalk+WCF series is complete, I will make the entire source code available.

Questions, comments or corrections?  Go ahead and leave a comment on my blog post about this article.

You can read more about BizTalk, SOA and enterprise architecture on my blog at http://seroter.wordpress.com.

 

 


Rate this article on a scale of 1 to 10 (47 votes, average 8)

Your vote :  

<< UncategorizedXALAN >>



Latest comments on this article
Admin
By Enrico on 11/18/2009 12:27:40 PM
Very good article and sample. Can i post this article in my Blog? Bye
By Ghada on 11/12/2009 10:25:57 AM
Thanks a lot for this useful series.
By Ghada on 11/12/2009 10:25:43 AM
Thanks a lot for this useful series.
By Ghada on 11/12/2009 10:25:23 AM
Thanks a lot for this useful series.
By Richard Seroter on 11/6/2008 10:26:47 AM
Yes, you can turn off all security for the service and see the message in clear text. Just make sure you set the security to "none" on both the client and service.
By Q on 11/6/2008 7:11:05 AM
I cant view the soap message as you did with TCPTrace, the whole message seems to be hashed as part of the WCF security, how can I disable the hashing to view the results via TCPTrace?
By Richard Seroter on 8/12/2008 10:25:50 AM
Seems to work fine for me ...
By Pradeep on 8/12/2008 1:10:26 AM
Hey Richard, It appears that the file "http://www.seroter.com/BlogPics/WordPress/Seroter.BizTalkWCFTutorials.zip" does not exist.
By Lakshmi Patil on 7/31/2008 8:59:42 AM
I want to see the source code of the BizTalk application. If any one haves can you please send to my mail ID
By Kumar on 7/28/2008 2:03:21 PM
Thanks for the quick turnaround. Will let you know how I found the samples. Thanks again.
By Richard Seroter on 7/28/2008 11:12:41 AM
Thanks for the heads up. My hosting provider had changed their security settings, which I have since relaxed.
By Kumar on 7/28/2008 10:55:27 AM
I was trying to access your code but it redirects me to a firwall warning message page.
By Kumar on 7/28/2008 10:55:07 AM
I was trying to access your code but it redirects me to a firwall warning message page.
By Joerg Fischer on 6/11/2008 3:41:30 AM
Hi, Thanks for the insight into typed fault handling - however, I miss a best practice for handling generic SOAP faults (which might even have no element within the detail section of the fault). Currently, I implement it using the SOAP envelope schema as provided by BizTalk and define these as fault messages - but I dislike this very much as it sticks the orchestration to the SOAP format in use. Any other suggestion?
By Richard on 5/30/2008 1:26:13 PM
Hey Salam, The code should be in the Seroter.BizTalkWCFTutorials.BizTalk project where the orchestrations and schemas for this scenario exist. There is another "operations" project with the data contract, and another with the WinUIHost.
By Salam on 5/27/2008 12:47:21 PM
Richard, well done and very nice article. I downloaded the code source from the provided link, it seems that code for this (part 1) is not in the zipped file, is it possible to have the code for reference. Thanks ina advance
By pqhgpqqa on 4/20/2008 2:39:33 AM
kxlobhct http://jiywamtf.com rhzkirpu kapdlqjs
By Richard on 3/25/2008 5:35:33 PM
Panch, my blog post has the source code included ... http://seroter.wordpress.com/2008/01/31/article-series-on-biztalk-and-wcf-part-i-operation-patterns/.
By Panch on 3/25/2008 4:06:13 PM
How to configure receive port/location to absorb the “starter” message which triggers the orchestration?
By Panch on 3/25/2008 10:54:04 AM
I am working on WCF/biztalk integration and found this article very useful.Can you please upload the code for reference.I am new to biztalk and looking for some sample to start with my requirements.


Leave a comment for this article
Your name
Your email (optional)
Your comment
Optional: Upload an attachment
Enter the code shown:

 
 

    Email TopXML