April 30, 2013 at 4:30 PM

On the latest version of BizTalk (2013): a new adapter was introduced for natively working with REST endpoints, using WCF technology: the WCF-WebHttp Adapter. 

After the beta version was released we could find some very good articles about this adapter, but since it is a new adapter there's a lot of ground to cover.
At the moment of my writing, the  MSDN website has very few information about it, so time to give something to the community... 

 


On this small article I will focus on using HTTP headers with the new adapter.

In this scenario I wanted to set HTTP content type at the header level. This could be done in two ways: using the adapter properties or writing in the message context. 

 

Adapter properties 

Using the adapter properties is a fairly simple task, we just need to go to our port properties and then adapter properties. On the last tab "Messages" we have a text area destined to Outbound HTTP Headers. Every HTTP header that we place here will be included on the message that will be sent (I'm using a send port for this example).

 

 

By default, WCF-WebHttp sends your message with as "Content-Type: application/xml; charset=utf-8", if you want to invoke a REST service with a GET request, for instance, you will have to insert the following code in the HTTP Outbound Headers:

Content-Type: application/http

And use a PassThruTransmit pipeline component, or another component that doesn't validate XML.


Message Context

If we need to set the HTTP headers at runtime we could do this mainly on orchestrations or pipeline components by writing the property on context.

 

We have two properties available to set in the headers: 

Property Name

Property Schema

Adapter

UserHttpHeaders

http://schemas.microsoft.com/BizTalk/2003/http-properties

HTTP

OutboundCustomHeaders

http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties

WCF-*


Both options will not raise any error if you try to write/promote them, but it won't work!
UserHttpHeaders is for HTTP adapter only, if you use it you will send the message as application/xml since the property isn't read by the adapter and since we are assuming that there is no HTTP header configured on the adapter properties.
The same goes for the OutboundCustomHeaders, it's for SOAP messages only (and using an XML structure), if you try to use it you will have the following error:
 

System.InvalidOperationException: Envelope Version 'EnvelopeNone (http://schemas.microsoft.com/ws/2005/05/envelope/none)' does not support adding Message Headers. 

If you happen to have an XML error it's probably because OutboundCustomHeaders is expecting an XML structure and you are not passing one.

 

So after dwelling on this issue for some time I inspected the new Biztalk 2013 property schema for WCF, and we can clearly  see some new properties related to the WCF-WebHttp adapter: 
 

Name

Type

Description

InboundHttpHeaders

xs:string

The HTTP headers present in the inbound message received over a HTTP transport

InboundHttpStatusCode

xs:string

The HTTP status code of the response message

InboundHttpStatusDescription

xs:string

The HTTP status description of the response message

InboundHttpMethod

xs:string

The HTTP Verb of the request message

OutboundHttpStatusCode

xs:string

The HTTP status code of the response message

OutboundHttpStatusDescription

xs:string

The HTTP status description of the response message

SuppressMessageBodyForHttpVerbs

xs:string

Removes the Message Body from the outbound request message, for the specified HTTP Verbs

HttpHeaders

xs:string

Sets HTTP headers for the outbound message

VariablePropertyMapping

xs:string

Provides the URL Template Variables and Message Context Properties mapping configuration

HttpMethodAndUrl

xs:string

Provides the HTTP Method and URL mapping configuration

 

In my scenario I wanted to use a send port, so the property that suits my purpose was HttpHeaders
All I had to do was write the content type into the property, without the need of promoting it. 

Here's part of my Execute() method of the custom pipeline component, where I set the message content type to application/atom+xml.


public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
{
    // Some non important logic here

    pInMsg.Context.Write("HttpHeaders", "http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties","content-type: application/atom+xml");

    return pInMsg;
}


Another important note that I should add, is about the adapter HTTP header limitations:
If you are planning to change the HttpHeader per message it won't work with a standard port, since by "design" the adapter uses the properties by port and not by message. If you need to change the header at runtime (per message) you will need to use a dynamic port instead.


And that’s it Smile

Ricardo Marques

 

 

 

Posted in: BizTalk | REST | WCF

Tags: , ,


April 3, 2013 at 4:05 PM

Some months ago, I was asked for an intervention regarding a SSL client certificate issue. There was a problem related to the setup of transport security (SSL) of a WCF service hosted in IIS 7.0, using client certificates that are mapped to a local account.  Let’s have a look.

 

The Setup

Server Setup

  • Wild card server certificate is installed in IIS (server level). Wild card is required, because we’re using multiple host names are configured.

          image

        image

 

  • The Certificate Authority is added to the Trusted Root Certification Authorities store (Local Machine)

        image

 

  • Website binding is configured to use https with the server certificate for SSL

        image

 

  • Website is configured to require SSL and to require client certificates

       image

 

  • Client certificate mapping is configured in order to map an individual client certificate to a specific Windows account. Configurable via this extension.

         image

       image

 

       This extension actually changes this configuration:

      image

 

  • An Allow authorization rule is configured for this Windows account

        image

 

  • Anonymous Authentication is enabled (Client Certificate is anonymous authentication)

        image

 

  • WCF service is configured for transport security

          image

 

Client Setup

  • The Certificate Authority is added to the Trusted Root Certification Authorities store (Local Machine)

           image

 

  • Client Certificate (containing private key) is added to the Personal certificate store (Local Machine).  This is required for the WCF client

          image

 

  • Client Certificate (containing private key) is added to the Personal certificate store (Current User).  This is required for browsing to the service via IE

         image

 

  • WCF Client is configured for transport security, providing Client Certificates:

          image

 

Problem Solving

The issue

When browsing to the service, for a particular web server, we’re not prompted to select a client certificate. Instead, we get this exception:

The page you are attempting to access requires your browser to have a Secure Sockets Layer (SSL) client certificate that the Web Server recognizes.

image

 

Troubleshooting

We configured another web server with exactly the same setup, which worked fine.  But still it didn’t work on that particular web server. Handy tools / commands during troubleshooting:

  • netsh http show sslcert
  • SSL Diagnostics

 

At the end, a warning in the System Event Log gave the solution. This entry is only written to the Event Log for the first call after the IIS service is restarted. That’s why we didn’t discover this Event Log warning earlier.

When asking for client authentication, this server sends a list of trusted certificate authorities to the client.  The client uses this list to choose a client certificate that is trusted by the server.  Currently, this server trusts so many certificate authorities that the list has grown too long.  This list has thus been truncated.

image

 

Root cause

During the handshake protocol for client certificate authorization, the server sends a list of Trusted Root Certification Authorities to the client.  The client will in this case only provide Client Certificates, issued by one of these Trusted Root Certification Authorities.  The problem was that the Trusted Root Certification Authorities list was too long on that particular server, so it was truncated before sent to the client.  Unluckily, our Root Certificate Authority was truncated from the list, so the handshake failed.

 

Solutions

There are two solutions to solve this issue:

  • The first solution is to clean up the Trusted Root Certification Authorities store (Local Machine) and remove all unnecessary certificates. Be aware that you don’t remove certificates that are required by Windows.

 

  • A second solution is to configure Schannel to no longer send the list of trusted root certification authorities during the TLS/SSL handshake process.  This can be done by adding this registry entry on the web server:

        HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL

        Value name: SendTrustedIssuerList
        Value type: REG_DWORD
        Value data: 0 (False)

 

Result

When browsing to the service, we’re now promoted for our Client Certificate. Now we can access the service:

         image

         image

Posted in: IIS | Security | SSL

Tags: , , ,


March 6, 2013 at 4:05 PM

In many scenarios, it could be required to have a send port with a dynamic behavior:

  • Send messages to a FILE location, containing the date of today
  • Send a notification mail to many different recipients
  • Dynamically change the URL of the backend web service, depending on the incoming request

 

Many developers would solve this by using dynamic send ports.  These ports allow you to configure all adapter properties, even the adapter type, at runtime.  I’m not a big fan of dynamic send ports, because it introduces some drawbacks:

  • Dynamic send ports are very difficult to troubleshoot (a hell for your operations team)
  • Dynamic send ports require your port configuration to be stored in a secure way (custom SSO application)
  • Dynamic send ports have a bigger performance hit (solved in BTS 2013)
  • Dynamic send ports don’t allow to specify an adapter handler (solved in BTS 2013)

 

That’s why I prefer using static send ports.  With a very easy trick, you can make static send ports partially dynamic.  Mostly it’s only the connectionstring, URI, path that must be changed at runtime.  This can be achieved in a custom pipeline component in the send pipeline:

 

 

This dynamic behavior works smooth for FILE and FTP adapters.  However, when using this mechanism on WCF send ports, there’s a caveat.  You will find out that the BTS.OutboundTransportLocation of the first message will be cached on the WCF send port.  So all subsequent messages will be sent to the same location.  This port configuration is cached until your send port configuration is modified or until your adapter send handler is restarted.  Luckily: there’s a way to disable this caching:

 

 

By setting the BTS.IsDynamicSend property to true, you force the WCF send adapter not to use the cache, but the runtime value instead.  More information on this setting can be found on MSDN.

Posted in: BizTalk | General | WCF

Tags: ,


October 24, 2012 at 4:19 PM

For a recent project I needed to send messages to BizTalk through an ASP.NET application.
The purpose of the ASP.NET website was to provide a simple user interface to send messages to BizTalk, where people can download / upload messages (with validation).

The users can first validate their message, this is done through a BizTalk pipeline that parses the message and does several checks to see if it is valid.

I exposed a request-response receive location using net named pipe binding that executes the validation.
The BizTalk pipelines parses the message and converts it to a “Validator Message” that contains the errors / warnings of the message.

Some of the files that are uploaded are pretty huge ( > 100 mb as a flatfile).
That is one of the reasons why I opted for the net.pipe binding, because this binding can implement streaming (note: not all bindings can implement streaming mode!).
Another reason why I opted for that binding is because this binding is perfect for communication between WCF applications on the same machine.

BizTalk

Here is how I set-up the BizTalk side.

I created one request-response receive port and added a receive location. I route the message I receive from the receive pipeline directly back to the send pipeline of that port, so I don’t need additional send ports.
You can see how to do this in another blogpost
The receive location uses the WCF-Custom adapter with the netnamedBinding.

I changed some default values, like the maxReceivedMessageSize, and made sure that “transferMode” is set to “Streamed”.

image

I also needed to change some settings in the “Messages” section.
I had to change the inbound and outbound message body, this is dependent on how you name the WCF interface in your .NET application (see section “.NET application” below).

Inbound Message Body

Extract the stream by selecting the xpath, in my case the xpath looks like following:

/*[local-name()='SubmitMessage' and namespace-uri()='http://App.services/BizTalk']/*[local-name()='Message' and namespace-uri()='http://App.services/BizTalk']

Also make sure that you set the Node Encoding to “Base64”, since we are sending a stream.

Outbound Message body

You also need the “wrap” the stream we receive back, so it is a valid response message according the interface of the WCF service we setup in the .NET application.

You can do this by setting the template. In my case I had to set it like following:

<ns0:SubmitMessageResponse xmlns:ns0="http://App.services/BizTalk">     
     <ns0:SubmitMessageResult xmlns:ns0="http://App.services/BizTalk">         
          <bts-msg-body xmlns="http://www.microsoft.com/schemas/bts2007" encoding="base64"/>     
     </ns0:SubmitMessageResult> 
</ns0:SubmitMessageResponse>

Be sure to include the “encoding” parameter so it encodes the message as base64.

image

Only thing left to do is set the uri of the receive location, example:  net.pipe://localhost/App/ValidatePricat

.NET Application

First thing to do is create the WCF interface.

I implemented the “IClientChannel” so I could use an OperationContextScope in my client to add a custom WCF header.

[ServiceContract(Namespace = "http://App.services/BizTalk")]
public interface IBizTalkSubmitService : IClientChannel {         
   [OperationContract(Action = "*", ReplyAction = "*")]         
   Stream SubmitMessage(Stream Message);  
}

 

Now for sending the stream to BizTalk.

FIrst create a channelfactory of the interface above, using the correct binding.
Make sure you set the transferMode to “Streamed”.

NetNamedPipeBinding b = new NetNamedPipeBinding("NetNamedPipeBinding_BizTalkService"); 
EndpointAddress epa = new EndpointAddress("net.pipe://localhost/App/" + operation); 
var myChannelFactory = new ChannelFactory<IBizTalkSubmitService>(b, epa);

Next create the client. You will see I am using an OperationContextScope. This is for adding a custom WCF header.
The reason why I need to add a custom WCF header is because the site is multilingual, so I implemented multiple languages in the BizTalk solution for returning error / warning messages concerning the validity of the message in the correct language.

You will see following line of code:

header.GetUntypedHeader("PropertyContainer", "https://R4A.Properties");

BizTalk will automatically promote the messageheader in the context. For this to work, you will need to create (and deploy) a propertyschema containing the property “PropertyContainer” (the one you defined in the above line of code) in the correct namespace.
The value of the “propertycontainer” is an XML document that has been encoded (but this could also be a simple string), I did this because I have multiple properties (language, some codes for validation, ..) and this way I can easily extract it in a custom pipelinecomponent in BizTalk.

This is the full code:

public Stream SendMessage(string operation, Dictionary<string, string> contextProperties, Stream message)        
{            
     NetNamedPipeBinding b = new NetNamedPipeBinding("NetNamedPipeBinding_BizTalkService");            
     EndpointAddress epa = new EndpointAddress("net.pipe://localhost/App/" + operation);           
     var myChannelFactory = new ChannelFactory<IBizTalkSubmitService>(b, epa);           
     
     IBizTalkSubmitService client = null;            
     Stream response = null; 
           
     try
     {                 
          client = myChannelFactory.CreateChannel();                
          using (OperationContextScope contextScope = new OperationContextScope(client))                 
          {                     
               if (contextProperties != null)                     
               {                         
                    XmlDocument xDoc = new XmlDocument();                         
                    XmlElement rootNode = xDoc.CreateElement("PropertyContainer");                        
                    foreach (KeyValuePair<string, string> pair in contextProperties)                         
                    {                             
                              XmlElement prop = xDoc.CreateElement(pair.Key, "https://R4A.Properties");                             
                              prop.InnerText = pair.Value;                            
                              rootNode.AppendChild(prop);                         
                    }                        
                    xDoc.AppendChild(rootNode);                        
                    var header = new MessageHeader<string>(HttpUtility.HtmlEncode(xDoc.InnerXml));                         
                    var untyped = header.GetUntypedHeader("PropertyContainer", "https://R4A.Properties");                         
                    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);                    
               }                    
               
               response = client.SubmitMessage(message);                 
          }                
          
          ((IClientChannel)client).Close();   
          
     }catch(Exception ex)             
     {                     
          ((IClientChannel)client).Abort();             
     }            

     return response;   
      
}

That’s it!
Now simply call the “SendMessage” method and you can send a stream to BizTalk and receive a stream back.
This way my website doesn’t need to read the message and no memory problems can be encountered, because everything works streaming.
And using the custom WCF header, I can still add some extra information to the message.

I couldn’t find a similar blogpost about this subject, so hopefully this will help you :)

Posted in: BizTalk | WCF

Tags: , ,


April 19, 2012 at 3:33 PM

Recently, we wanted to create multiple WCF services that should communicate with each other through the netMsmqBinding binding and we wanted to use a clustered MSMQ service.
However we encountered some problems and wanted to share them with you.

Situation: We run MSMQ as a part of resource group on a cluster. The service is hosted in WAS and the application pool runs under a functional user.

1. Without Windows Integration

Note: In our WCF service the security mode is set to "None".

When our services ran and started to communicate with each other we did not get any messages  in the queue as we expected, actually we did not find any message on the clustered MSMQ but we saw in our tracing that the WCF service did not report any error to place a message on the queue.

After some investigation we found all test messages in the local System queue “Transactional dead-letter messages” with the report “Access denied”.

So our first thought was to check the MSMQ security on that particular queue: we started up mmc, connected to the clustered resource e.g. “MyclusteredResource” to check on the MSMQ security:

 


There we wanted to check the security on a queue (by right clicking on the queue) we noticed we did not have a properties option.

 


It seems that you cannot configure MSMQ security when connecting through the mmc console.
Microsoft pointed out that we should use an other tool to configure the security (mmcv.exe).

You can download mmcv.exe : http://www.microsoft.com/download/en/details.aspx?id=18189

 

You use it as follows on the active node (Where the MSMQ resource is running):  
"<drive>:\<directory>\mmcv -s <Network Name of the clustered MSMQ resource>" 
 

When you drill down to the MSMQ queues we finally got the properties option. So we went on to check the security.

 

Note: If you are running the mmcv.exe tool on the non-active node you will not find the Message Queueing option.

It seemed that Everyone had full control and yet we got the error message “Access denied”

 

After a bit of searching we found the following KB article: http://support.microsoft.com/default.aspx?scid=kb;EN-US;952570 and following blog http://blogs.msdn.com/b/tomholl/archive/2008/07/13/msmq-wcf-and-iis-getting-them-to-play-nice-part-2.aspx

This explained why we got the error message the message does not include the security header. Therefore, the message does not contain the user ID of the sender "

 

So we added the “ANONYMOUS LOGON “ to the users and gave him the appropriate rights to read / write on the queue.

 

After that we ran a test and all messages were delivered on the clustered MSMQ! 

In the next step I’ll show you how you can check and enable the Windows Integration on your server...

 

2. With Windows Integration

Through the Features option in the server manager (Server 2008) you need to check if Directory Service Integration is enabled. Be aware that you need to do this for each node.

 

 

 

Once this feature is installed and your resources went online, an MSMQ object should be created in the active directory record of your network resource hosting your MSMQ e.g. “MyclusterresourceYou” can check it by the following steps:

Open the Active directory Users and Computers.

 

Through the View otpion select "Users, groups and computers as containers"

 

Finally search for your network resource and check if it has a MSMQ object.

 

 

If you don’t find any MSMQ object it is possible that when Directory Service Integration is installed afterwards no MSMQ object is created (more info: http://support.microsoft.com/default.aspx?scid=kb;EN-US;935498)

 

Once that is fixed, for Windows Integrated security you only need to add your user in the MSMQ security with mmcv.exe

Change your WCF security mode to "Transport" and enable the msmqAuthentication mode so your WCF service is ready to use Windows Authentication.

 

 

When you get the following error while starting your WCF service: "Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled. The channel factory or service host cannot be opened" then you need to check the MSMQ object in the active directory (see previous steps).

 

Jonathan Maes

 

 

Posted in: MSMQ | WCF

Tags: , ,


April 3, 2012 at 11:52 AM

Many of us at Codit already installed the WCF LOB SDK multiple times. And in the process we have learned to know the caveats that come with the installation:
- 32 bit vs 64 bit
- Adapter Pack installation (again, 32 bit vs 64 bit)
- Enterprise application installation

Now since BizTalk 2010, there is a great wizard added to the installation screen if you click “Install Microsoft BizTalk Adapters”:

image 

The screen shows up like this once you go through the entire installation:

image

Please note that the above screenshot is from a production server where I don’t have Visual Studio installed, so I could not install the developer tools (hence the warning)

It is a very welcome change, because before BizTalk 2010, people did not know exactly what they needed to install and in which order.
Now the screen gives you a very handy wizard-style interface.

Now recently I had a strange error: on a 64-bit machine I went through the installation.
I was sure that everything was installed correctly and in the right order!

I checked all machine.config files (for framework 2.0 and 4.0, both 32-bit and 64-bit) and all had the necessary entries added.
However, there was no way I could see/add the WCF LOB Adapters in the BizTalk console:

image

I went through a lot of online searching until I accidently stumbled upon the BizTalk modify wizard:

image

It happens that the WCF Adapter components in BizTalk were not installed, so the WCF adapters were not showing up for a good reason!

When I checked both checkboxes (WCF for BizTalk Runtime and Administration Tools And Monitoring), installed it on both nodes and re-opened the BizTalk consoles, I could add the WCF adapters I needed.

image

I hope this helps at least someone!

Posted in: BizTalk | LOB | WCF

Tags: , , ,


February 19, 2012 at 12:26 PM

A while ago I had a little surprise with a demo project.
The project consists of a client application, a claims aware WCF service and AD FS as token issuer.

This demo was working fine until now...
Without changing anything, authentication always fails with this error message (see WIF tracing):

ID4175: The issuer of the security token was not recognized by the IssuerNameRegistry. To accept security tokens from this issuer, configure the IssuerNameRegistry to return a valid name for this issuer.

Offcourse my token issuer certificate was added to the 'trustedissuers' collection on the WCF service, so something must have changed in AD FS.

The signing certificate in AD FS shows this:

As you can see, there are two signing certificates (I had one before). The second signing certificate was created by AD FS automatically because my signing certificate was reaching it's expiration date. This feature - AD FS creating a new self-signed certificate when the old one nears expiration - is called Auto Certificate Rollover.

When using self-signed certificates, auto certificate rollover is on by default.
AF FS will use the signing certificate marked as 'Primary' to sign issued tokens.
The only thing I need to do is adding the new certificate to the trusted issuers collection as shown below:

 

Note: The reason why my sample failed is that I use the out-of-the box 'ConfigurationBasedIssuerNameRegistry' class to resolve the trusted issuer. This class uses the certificate thumbprint to match certificates. Obviously the certificate thumbprint changed when auto certificate rollover issued a new signing certificate. You can avoid this by implementing you own class and for example use the subject name to match issuers.

After adding the thumbprint of the new signing certificate to the trustedIssuers section, the sample should work again ... unless ...

My signing certificate is a self-signed certificate, but the newly created certificate is not trusted on the WCF machine. This results in this error:

ID4257: X.509 certificate 'CN=ADFS Signing - WIN-BEJU5AI4TP7.pbdev.CODit.eu' validation failed by the token handler.

The self-signed signing certificate should be added to the trusted root store of the WCF machine. The action you need to take to make sure the certificate passes validation depends on the certificateValidation mode you use. Mine was set on chaintrust, so adding it to trusted root will do. If you use peertrust, add the certificate to the trusted people store. If you use custom it depends on your implementation.

 

Peter Borremans

Posted in: Security | WCF | WIF

Tags: , , , ,


January 13, 2012 at 11:24 AM

This blog post contains some guidelines for consuming web services, with a focus on exception handling.  We will both handle pure messaging scenario and web service calls from within an orchestration.  I also make a distinguishment between asynchronous and synchronous flows.  Synchronous means that the flow needs to return a message to the original caller.  So in case of troubles, a SoapFault needs to be returned to the calling application.  In an asynchronous flow, you just need to make sure that your web service call is resumable. 

 

Messaging Scenario – Asynchronous

When an error occurs during the web service call, the default behavior of BizTalk retry 3 times and will suspend the request message on the BizTalk Send Port and this instance will be resumable.  This is the perfect behavior for this asynchronous process.

 

Messaging Scenario - Synchronous

If you are in a synchronous process, a suspended Send Port will lead to a timeout on your Receive Port.  In this scenario you need to enable "Propagate Fault Message" on the Send Port and a SoapFault will be returned to the original caller.  Also think about the Retry Count and Retry Interval settings, because a bad configuration can also lead to timeouts.

image

 

Orchestration - Asynchronous

When you consume a web service from within an orchestration, it's getting more complex.  If the consumed web service throws an exception, BizTalk creates by default 2 suspended service instances.  Resuming them does not always have the expected behavior.

 

-  The Orchestration is suspended.  A resume will not change anything to the state of the Orchestration.
-  The Send Port is suspended.  A resume will resume the web service call as expected, but the Orchestration will not be able to continue processing afterwards.

 

image

How can we now achieve a resumable web service call?

 

First of all enable "Propagate Fault Message" on the Send Port.


Also modify the calling orchestration:

-  You need to create a loop.  This loop continues as long as the Boolean bSuccess equals false.

-  Modify the logical Orchestration Send Port and add a Fault Message.  To keep it general, you can choose the SoapFault (which is part of the Microsoft.BizTalk.GlobalPropertySchemas).

clip_image002        clip_image003

-  Add an exception handler to the web service call. Catch the Fault Message that was returned.  Add a suspend shape for human intervention. Note that it’s a good practice to also add an extra exception handler which catches a System.Exception.

-  If the web service call fails: set bSuccess == false in the exception handler.  If the call succeeds, set bSuccess == true, so the orchestration will exit the loop.

 

The result should look like this:

image

 

Now we've created a resumable web service call from within an orchestration.  When testing the orchestration in a failure scenario, you will see that there are still two suspended service instances:

-  The Orchestration is suspended.  This is the one that we've made resumable.

-  The Send Port is suspended.  To avoid this second service instance to be suspended, you can enable "Routing for Failed Messages".  This will generate an ErrorReport, instead of suspending the Send Port.  Subscribe on the ErrorReport with the filter ErrorReport.ErrorType == “FailedMessage”.

 

clip_image006

 

Orchestration - Synchronous

In this scenario, you will also need to catch the SoapFault (or other exception) and make sure that you don’t end up with suspended send port instances. See “Orchestration – Asynchronous”


The extra functionality that you’ll need to add is returning a SoapFault to the original caller.

- Add a Fault Message to the Request/Response receive port of your orchestration.

- You can choose to return a typed Fault or, to keep it general, a SoapFault (which is part of the Microsoft.BizTalk.GlobalPropertySchemas).

- Make sure you return the catched SoapFault (or the created SoapFault in case of other exception) in case of errors.

- Remark that you’ll need to add a decide shape to determine you’re in a success/failure scenario. Otherwise, the compiler will fail (complaining about unconstructed messages).

 

clip_image002[4]

 

Again, think about the Retry Count and Retry Interval settings on the send port.

 

Toon Vanhoutte

Posted in: BizTalk | SOA | WCF

Tags: , ,


By sam
August 11, 2010 at 2:12 PM

Recently I was in Redmond for the BizTalk VTS Summit, with a bunch of colleague BizTalk experts from all over the world.  During one of the discussions we had, a question came up about the fact that it seemed that to host HTTP endpoints, it is required to have IIS as the real host configured.

After my suggestion that is was perfectly possible to bypass IIS in this process, it looked that quite a number of attendees didn’t know about this.  And that’s the reason why I decided to add it to our blog…

WCF-Custom vs WCF-CustomIsolated

First of all, I think it is a best practice to avoid using the non-WCF-custom adapters (like WCF-WSHttp, etc).  I always suggest colleagues and customers to use the WCF-Custom or WCF-CustomIsolated adapter, since they are the only adapters that provide the maximum capabilities of WCF in BizTalk.  The other WCF-* adapters only provide a subset of the various binding and behavior settings, specific for their binding, which results in an adapter change, when a more advanced setting is needed one day.

The WCF-Custom adapter, is the adapter that is used to host WCF endpoints inside BizTalk.  The WCF-Isolated adapter is hosted in a BizTalk Isolated Host, which is typically IIS.

The BizTalk WCF Service Publishing wizard

To expose an orchestration or a schema as a WCF service in BizTalk, the BizTalk WCF Service Publishing wizard is the typical way to use.  In this wizard, the orchestration or schema needs to be selected and a choice between three adapters is possible: WCF-BasicHttp, WCF-WSHttp, WCF-CustomIsolated. 

The last step of the wizard is used to create a web directory in IIS, where the BizTalk svc file will be created that hosts the custom WCF Service Host that will link through to the BizTalk Receive location. 

WCF Service type WCF Service Location

Unfortunately, the WCF Publishing wizard does not allow to select the ‘In-Process’ adapters.  All of the three adapters/bindings are only available through an isolated host and required IIS.

Hosting the endpoint in the BizTalk process

To host the endpoint inside the BizTalk process, we need to manually create the WCF receive location.  To do so, we just need to select the WCF-Custom adapter and use the desired binding: BasicHttpBinding or WsHttpBinding. 

The following steps need to be used for this:

  1. Create a new receive location with the desired name
  2. Select the WCF-Custom adapter and open the properties for this adapter
  3. Specify an address for the endpoint (picture 1) Take into account that when IIS is already running on the machine, you might need to specify a different available port.
  4. Select your binding (or use the customBinding for full flexibility) in the Binding tab page. (picture 2) and set all desired binding properties to their correct setting.
  5. In the Messages tab page, you can also specify that failed request messages need to be suspended and that exceptions should be returned to the consumer. (picture 3)

wcf1 wcf2 wcf3

Metadata publication

One downside of this way of work is the metadata publishing.  If you would query the exposed endpoint for the WSDL, you would get to see the WSDL of the generic BizTalk WCF Service Host with the 5 operations.

Therefore, it is needed to publish the metadata endpoint to IIS and provide that endpoint to the consumers of your in-process service.  But this way of work, is similar to the other protocols (like netMsmq, netTcp…)

Advantages

  • Consistent approach for all binding types, independent of protocol.
  • No extra configuration / deployment needed (specific IIS security on IIS application pools, etc)
  • Performance (no extra hop)

Sam Vanhoutte, CODit

Posted in: BizTalk | WCF

Tags: , ,


April 21, 2010 at 3:34 PM

In this post I will talk about setting up a trace for the WCF-Adapter. This post should be a good addition to some previous posts I made about the WCF-Adapter.

Communicating with SAP through WCF : Send and Receive Ports

Communicating with SAP through WCF : Generate SAP schemas

1.  Tracing within the Adapter

 

Add the following to the configuration section of your BizTalk configuration file, BTSNTvc.exe.config which is present under <system drive>:\Program Files\Microsoft BizTalk Server 2006:

 

<system.diagnostics>

    <sources>

      <source name="Microsoft.ServiceModel.Channels" switchValue="Warning">

        <listeners>

          <add name="eventlog" />

        </listeners>

      </source>

      <source name="Microsoft.Adapters.SAP" switchValue="Warning">

        <listeners>

          <add name="eventlog" />

        </listeners>

      </source>

    </sources>

    <sharedListeners>

      <add name="eventlog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/>

      </sharedListeners>

    <trace autoflush="false" />

  </system.diagnostics>

This will enable Warning level tracing (Errors + Warnings).  Replace APPLICATION_NAME with the name of your application as you want it to appear in the event viewer. Now you can see the errors and warnings - even the ones that were thrown to SAP.

If not possible to write to event log or if too bulky, then alternatively, you can put the following instead of the listeners “event log” if you want to log to a file. You will then need the tracing viewer (see below):

 

<add name="xml" type="System.Diagnostics.XmlWriterTraceListener"

   traceOutputOptions="LogicalOperationStack"

          initializeData="C:\log\WCF\AdapterTrace.svclog" />

ATTENTION: Trace files can become huge. Remember to stop tracing once issues have been solved.

2.  Tracing the Adapter and the LOB Application

To diagnose issues that you suspect are related to the LOB application, you must enable tracing for communication between the adapter and the LOB application. Adapters also depend on LOB tracing (client/server side) to access this information. The SAP adapter enables adapter clients to turn on tracing within the SAP system by specifying the "RfcSdkTrace" parameter in the connection URI. You must specify this parameter to enable the RFC SDK to trace information flow within the SAP system. For more information about the connection URI, see The SAP System Connection URI.

This parameter is specified in the SAP binding URI of the BizTalk WCF adapter:

 

Additionally, you can also create an RFC_TRACE environment variable that sets the level of tracing for the RFC SDK. RFC_TRACE is an environment variable defined by SAP and is used by the RFC SDK. If this variable is not defined or is set to 0, the RFC SDK tracing level is bare minimum. If the variable is set to 1 or 2, the tracing level is more detailed.

 

RFC_TRACE = 2
RFC_TRACE_DIR =
C:\log\LOB

Note: Irrespective of whether the RFC_TRACE environment variable is set, the RFC SDK tracing is enabled only if setting the "RfcSdkTrace" parameter to true in the connection URI (see in STEP 2). The value of this environment variable solely governs the level of RFC SDK tracing. If RfcSdkTrace is set to true, the message traces between the adapter and the SAP system are copied to the “system32” folder on your computer. To save the RFC SDK traces to some other location, you can set the RFC_TRACE_DIR environment variable. For more information about these environment variables refer to the SAP documentation.

3.  Viewing the Traces

You can use the Windows Communication Foundation (WCF) Service Trace Viewer tool to view the traces. For more information about the tool, see "Using Service Trace Viewer for Viewing Correlated Traces and Troubles" at http://go.microsoft.com/fwlink/?LinkId=91243 .

Enjoy!

Glenn Colpaert 

Posted in: BizTalk | WCF

Tags: , , ,