Showing posts with label ports. Show all posts
Showing posts with label ports. Show all posts

Monday, 22 December 2008

How can I use Fiddler to debug BizTalk messages?

When using HTTP, SOAP or WCF send ports it can be incredibly useful to view the content of messages that are sent on the wire. This allows you to inspect the headers (SOAP or HTTP). Fiddler is a simple but fantastic tool to allow you to do this.

By default, Fiddler will not trace any messages sent to endpoints by BizTalk as it does not use WinInet. However, BizTalk send ports can be configured to use a proxy allowing Fiddler to intercept them. On the Send Port tick the Use Proxy checkbox and set the Server to 127.0.0.1 and the port to 8888. For dynamic ports, set the following properties (as applicable to the adapter being used)

// Debug via fiddler
msgSendRequest(SOAP.UseProxy) = true;
msgSendRequest(SOAP.ProxyAddress) = "127.0.0.1";
msgSendRequest(SOAP.ProxyPort) = 8888;

Note that this needs to be removed when Fiddler is not running since traffic directed to the proxy will not be received by anything.

Wednesday, 20 February 2008

Dynamic SOAP Adapters

Following on from my previous post concerning dynamic HTTP adapters, this time I'll extend the same concept to the SOAP adapter. Many of the techniques previously presented are still applicable but the SOAP adapter has it's own little idiosyncrasies which once explained are easy enough to overcome.

The first issue is that of a proxy. In traditional .NET applications, when using a web service it is typical to add a web reference which, under the covers will generate a proxy to the remote service based on its WSDL definition. This is also what would happen if you add a web reference in your orchestration and use a static SOAP send port. However, for a dynamic send port we don't want to create a web reference - we'll generate the proxy manually using the wsdl.exe tool as follows:

C:\>wsdl /l:CS /o:c:\temp\wsdl http://localhost/CalcWebService/CalcService.asmx?wsdl
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'c:\temp\wsdl\CalcService.cs'.

Here we have generated a proxy class from the WSDL of the web service. Add this to a new Class Library project. Ensure the resulting assembly is strong named and add it to the GAC. Note that the WebMethod to be called should have a signature as below that will accept an XML message and return one too. If an alternative method signature is required it will be necessary to update the proxy class to act as an facade between the required signature and the web service one.

[WebMethod]
public XmlNode MyMethod(XmlNode Message)

As with the HTTP example, we'll be invoking a dynamic adapter from an orchestration, setting adapter properties to change its behaviour at runtime. Again, add a request/response send port to the orchestration port surface and mark its type as Dynamic. The only other configuration required on the port is to specify the pipelines to be used, in this case XmlTransmit and XmlReceive. Connect up the request and response operations to the relevant send and receive shapes in the orchestration. Note that the operation on the send port should have the same name as the WebMethod being called.

Prior to sending the message set the following send port properties:

// Assign message
msgSendRequest = msgReceiveRequest;


// Set base properties
MySendPort(Microsoft.XLANGs.BaseTypes.Address) =
                     "
http://localhost/CalcWebService/CalcService.asmx";
MySendPort (Microsoft.XLANGs.BaseTypes.TransportType) = "SOAP";

// Set HTTP adapter specific properties
msgSendRequest(BTS.SOAPAction) = "Add";
msgSendRequest(SOAP.MethodName) = "Add";
msgSendRequest(SOAP.AssemblyName) = "CalcTest.CalcWebServiceProxy.CalcService,
    CalcWebServiceProxy, Version=1.0.0.0, Culture=neutral,
    PublicKeyToken=b713f1108bae3109";
msgSendRequest(SOAP.TypeName) = "CalcTest.CalcWebServiceProxy.CalcService";

Some important points to note here:

  1. The TransportType is a means of informing BizTalk which adapter you want to use. If it is omitted the prefix of the Address (in this case http://) will be used to query an alias table to lookup the adapter to use. By default this will use the HTTP adapter, therefore we set the Microsoft.XLANGs.BaseTypes.TransportType property to "SOAP" to ensure that the SOAP adapter is targeted.
  2. The BTS.SOAPAction and the SOAP.MethodName are both set to the name of the WebMethod being invoked.
  3. The SOAP.AssemblyName must be populated with the details of the class name and assembly of the proxy to be used. This value takes the form Namespace.ClassName, Fully Qualified Assembly Name. Set this to the details of the proxy assembly created and GAC'd earlier.
  4. The SOAP.TypeName must also be set to the full name of the proxy class i.e. Namespace.ClassName. Not sure why this is required again but if it is not set an error occurs.

OK, now you should be good to go. Build, deploy and (hopefully) watch those SOAP requests flying to and from your web service. Whilst it's a little more fiddly to setup that the HTTP equivalent, using a dynamic SOAP adapter is a really powerful technique for creating flexible and extensible BizTalk applications.

Jon Fancey has taken this a step further by creating a more generic SOAP router. Check it out.

Tuesday, 19 February 2008

Dynamic Send Ports

Part of the project I'm currently working on involves sending XML messages to a variety of trading partners. Each partner has several products each of which could require different port settings (URL, credentials, timeout, retry strategy). Another variable is the transport type. Currently all support plain XML over HTTP but in the future SOAP may be a requirement. As we have up to 1000 different partner/product combinations to support dynamic ports seem like a logical choice.

So how do you implement dynamic HTTP and SOAP send ports? Let's start with HTTP first as it's a little more straightforward.

Assuming that the orchestration is in place, add a request/response send port to the port surface and mark its type as Dynamic. The only other configuration required on the port is to specify the pipelines to be used and to connect up the request and response operations to the relevant send and receive shapes in the orchestration.

dynamicsend1

Prior to the send shape (I have used the message assignment shape that builds the request message) add the following code.

// Assign message
msgSendRequest = msgReceiveRequest;

// Set base properties
MySendPort(Microsoft.XLANGs.BaseTypes.Address) = "
http://localhost/testpartner/test.aspx";
MySendPort(Microsoft.XLANGs.BaseTypes.TransportType) = "HTTP";

// Set HTTP adapter specific properties

msgSendRequest(HTTP.AuthenticationScheme) = "Basic";
msgSendRequest(HTTP.Username) = "mark";
msgSendRequest(HTTP.Password) = "pwd";

This code sets up the address URI and the transport type to be used. The TransportType is a means of informing BizTalk which adapter you want to use. If it is omitted the prefix of the Address (in this case http://) will be used to query an alias table to lookup the adapter to use. For some prefixes there are multiple adapters that could handle the request. For http:// it could be the HTTP, WCF-Basic or WCF-WSHttp so the TransportType property can be used to explictly choose the correct adapter. In this instance I could have omitted the TransportType since the HTTP is the default for http:// addresses.

Next I have set some properties that are specific to the HTTP adapter. In this instance I have just configured the authentication details but there are lots of other that can be used. Typically these settings could be looked up from a database or other configuration store and set dynamically based on the request.

And that's it! The request should then be routed to the URI configured in code above using the HTTP adapter. This is a very powerful technique to add flexibility to your application. I'll continue by demonstrating how to use the same technique for the SOAP adapter in a future post.