Tag Archive: WCF


The book is now available, well done co-authors, reviewers and Packt Publishing team.

Connected Pawns

I am pleased to announce “SOA Patterns with BizTalk Server 2013 and Microsoft Azure – Second Edition” by Mark Brimble, Johann Cooper, Coen Dijgraaf and Mahindra Morar can now be purchased on the Amazon or from Packt. This is based on the first edition written by by Richard Seroter. Johann has given a nice preview of the book here.

This is the first book I have co-authored and I can now tick that off on my bucket list. It was an experience to work with such talented co-authors and I was continually amazed how they rose to the occasion. I agree with Johann’s statement about being privileged to write the second edition of what was the first BizTalk book I ever owned.

As I updated chapters I was continually struck by how little had changed. We added new chapters, Chapter 4, Chapter 5, and Chapter 6…

View original post 125 more words

Advertisements

For those who extend their BizTalk solutions using WCF behaviors, a common challenge is working out how to flow details from your BizTalk message into your WCF behavior extension so that you can access them in the extension.

Luckily for you, BizTalk and WCF are like a match made in heaven and work together really seamlessly.  BizTalk context properties flow through to WCF behavior extensions and are easily accessible, and it is quite possible to flow details back from a WCF behavior to the response message’s BizTalk context as well.

For the rest of this blog post I will assume that you have already setup a WCF Message Inspector extension and are making use of it on a WCF send port in BizTalk (a lot of what I demonstrate should be applicable for other types of behavior extensions and for receive locations as well).  I will demonstrate how you can access BizTalk context from within your Message Inspector, and also how you can set context property values on the response message as well.

For your request messages this is a no brainer.  Every single context property that was attached to the message in BizTalk will automatically flow through to your WCF Message Inspector in the form of a property bag attached to the request message. Context property values can be fetched out of the property bag by using the context property namespace#name as in the following example which fetches the BTS.Operation context property value (you would normally of course want to check whether you are getting a null value back before converting it to a string to avoid a NullReferenceException in case the context property didn’t exist in the property bag).

        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
            string _BTSOperation = request.Properties["http://schemas.microsoft.com/BizTalk/2003/system-properties#Operation"].ToString();
            ///Do some stuff with the BTS Operation
        }

Leveraging your context properties in WCF behaviors opens the door towards much more cohesive solutions in which you use the right types of components for the right kinds of problems. A good example of this would be scenarios in which you need to calculate an OAUTH signature, which is probably best done in a WCF behavior, however you might have otherwise been tempted to do it in a pipeline component instead since you needed access to BizTalk context properties.  Knowing that you can flow your context properties through to your behavior extensions keeps your options open.

How about the flip side when you want to flow some data back from your WCF behavior to BizTalk context properties. Here your options diverge slightly depending on whether you are dealing with a SOAP or RESTFul service based on the WCF-WebHttpBinding binding, and you’ll also find that all options include a bit more difficulty.  You can choose to pass the context in the form of inbound SOAP headers or inbound HTTP headers as demonstrated in the following code snippet.

        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            //Writing to WCF.InboundHttpHeaders context property
            System.ServiceModel.Channels.HttpResponseMessageProperty httpHeaders = (System.ServiceModel.Channels.HttpResponseMessageProperty)reply.Properties["httpResponse"];
            httpHeaders.Headers.Add("ContextHTTPHeader", "Content property value");

            //Writing to WCF.InboundHeaders as well as to http://contextproperty#ContextSOAPHeader context property
            var header = new MessageHeader<string>("Content property value");
            var untypedMessageHeader = header.GetUntypedHeader("ContextSOAPHeader", "http://contextproperty");
            reply.Headers.Add(untypedMessageHeader);
        }

So if I actually use this behavior on a WCF SOAP based send port what will the result look like?

Context

We can see that populating an inbound HTTP header in the WCF behavior has resulted in an HTTP header called ContextHTTPHeader being appended to the end of the WCF.InboundHttpHeaders context property. You can use the BRE Pipeline Framework to extract individual HTTP headers easily. The value of the context property looks like the below.

X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Connection: Keep-Alive
Content-Length: 535
Cache-Control: private, max-age=0
Content-Type: application/soap+xml; charset=utf-8
Date: Wed, 01 Jul 2015 08:59:10 GMT
Server: WWW Server/1.1
ContextHTTPHeader: Content property value

Populating the inbound SOAP header in the WCF behavior actually results in it showing up in two context properties. The first is in the WCF.InboundHeaders context property, and the value looks like the below.

<headers><ContextSOAPHeader xmlns=”http://contextproperty”>Content property value</ContextSOAPHeader></headers>

The second context property which you’ll notice is a custom context property with the same name/namespace as the SOAP header which we created – http://contextproperty#ContextSOAPHeader.

<ContextSOAPHeader xmlns=”http://contextproperty”>Content property value</ContextSOAPHeader>

In both of the above scenarios you’ll notice that it isn’t too simple to actually extract the value that you set for your inbound SOAP header. Once again, the BRE Pipeline Framework could help you extract the value using regex.

Note that if you try to set an inbound SOAP header in a WCF behavior on a WCF-WebHttp send port you will be met with the following exception.

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

One of the key areas to focus on when using Service Bus Relays to expose on premise BizTalk hosted WCF services externally without making any firewall changes is availability. Service Bus Relay endpoints in Azure will only be enlisted upon initialization of your on premise service. NOT when your application pool starts, NOT when you create your Service Bus Namespace, but only when a request is made to the local endpoint of the service. Browsing (effectively an HTTP GET) to the local .svc file on the BizTalk VM serves just as well to enlist the Azure Service Bus Relay endpoint.

A common solution to this problem is to use the IIS 8.0 Application Initialization module which has been really well documented here. What this effectively results in is that your .svc file is activated any time IIS resets, your application recycles, or your app domain reloads. The Application Initialization module is also available for IIS 7.5 and can be downloaded here.  This results in your relay endpoint being enlisted in Azure.

Application Initialization is an absolutely core part to any Service Bus Relay service, regardless whether the backend service is a vanilla WCF service or based on a BizTalk receive location. No WCF Service Bus Relay solution should be built without this in mind.

However, I found that when dealing with BizTalk there is an additional consideration to keep in mind. What I observed is that if your BizTalk environment encounters outages due to an inability to connect to the BizTalk Management database (due to network or database issues) the services (not the application pool, not IIS, the services themselves!) will get shut down by BizTalk. When BizTalk recovers from the outage the services will not get spun up again until someone calls on the local service endpoint or browses to the local .svc file. Because the IIS application pool has not restarted, Application Initialization will not kick in and thus your endpoint will not be enlisted in Azure.

The solution I have put in place is to generate keepalive requests to the local endpoint every minute. This makes me feel a bit dirty, but I haven’t found a better solution yet, so I will detail it for you. If you can think of a better option, please do share it and I will update this post.

What I have done is setup a receive location based on the Scheduled Task adapter that generates a keepalive message every one minute (I’ve chosen quite a regular interval because availability is really key to my services, choose your interval appropriately) that gets routed to a solicit-response WCF-WebHttp send port (actually in my case 4 send ports, one corresponding to each service being exposed by Service Bus Relays that I want to keep alive). The endpoint address on this send port is pointed towards the .svc file for the service I want to keep alive, and the “HTTP Method and URL Mapping” section of the send port’s configuration is set to “GET” since we want to perform an equivalent action to browsing to the .svc file.

webhttp

One more thing of note is that since this is an HTTP GET, the target endpoint is not expecting a request message body, so we must use the WCF-WebHttp adapter’s functionality to supress it, as per the following screenshot.

Supress

Because I’m not really interested in the response messages being returned to the send port, I route these messages to a file send port which uses the BRE Pipeline Framework to discard the message (utilizing the NullifyMessage vocabulary definition in the BREPipelineInstructions.SampleInstructions.HelperInstructions vocabulary).  The address on the send port can be set to any folder since no file will actually get written out by the adapter.
Discard

Using the WCF-WebHttp adapter and pointing it directly to the .svc file helps minimize the requirement for additional development since you aren’t forced down the path of exposing additional operations in your service to cater for the keepalives.

While working on a project using the WCF webHttpRelayBinding binding with SAS based authentication over transport security, I found that my services were taking a very long time to spin up (30-60 seconds) and that my runtime performance was a bit less than optimal in terms of latency (and I had proven that the latency was not a result of my backend service).  To give you an idea what I was working with, my web.config file had contents similar to the below in the system.serviceModel element.

      <endpointBehaviors>
        <behavior name="sharedSecretClientCredentials">
          <transportClientEndpointBehavior>
            <tokenProvider type="SharedAccessSignature">
              <sharedAccessSignature keyName="keyname" key="key" />
            </tokenProvider>
          </transportClientEndpointBehavior>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkServiceInstance" behaviorConfiguration="ServiceBehaviorConfiguration">
        <endpoint name="RelayEndpoint" address="https://sbnamespace.servicebus.windows.net/service" binding="webHttpRelayBinding" bindingNamespace="http://tempuri.org/" bindingConfiguration="RelayEndpointConfig" behaviorConfiguration="sharedSecretClientCredentials" contract="Microsoft.BizTalk.Adapter.Wcf.Runtime.ITwoWayAsync" />
      </service>
    </services>
    <bindings>
      <webHttpRelayBinding>
        <binding name="RelayEndpointConfig">
          <security relayClientAuthenticationType="RelayAccessToken" mode="Transport" />
        </binding>
      </webHttpRelayBinding>     
    </bindings>

I didn’t observe such problems on my development VM (which I was running with pretty much no firewalls behind it), but did observe this on my client’s UAT environment. This was in spite of following Microsoft’s guidelines that suggest that you should have outbound TCP ports 9350-9354 open on your firewall to enable Service Bus connectivity.  I went through an exercise using the PortQuiz website to prove that these ports were indeed accessible from the UAT server so the performance issues were puzzling.

Next up, I spun up a fiddler capture.  To start with I applied the below filter into Fiddler to get rid of the extra noise.

tcp.port eq 9350 || tcp.port eq 9351 || tcp.port eq 9352 || tcp.port eq 9353 || tcp.port eq 9354

I then initialized some of my services (I shut them down forcibly and then spun them up again) to observe which ports were in use.  I saw that the conversation with Service Bus was being initialized on port 9350 as expected, however that appeared to be the end of the story.  I wasn’t seeing any comms on ports 9351-9354.  I then right clicked one of the displayed records in WireShark and chose “Conversation Filter -> IP” which updates the filter such that it displays anything with a source or destination IP address matching those on the selected record.

This suddenly resulted in a whole lot more records being displayed and helped me get to the root of the issue.  What I was observing was that after Service Bus made the initial connection on port 9350, it attempted to continue the conversation on port 5671 (AMQPS or AMQP over SSL) which hadn’t been opened on the firewall.  This connection attempt was obviously failing, and the observed behavior was that some retries were attempted with fairly large gaps in between until Service Bus finally decided to fall back to port 443 (HTTPS) instead.  Pay particular attention to the lines in the following screenshot with the numbers 1681, 2105, and 2905 in the first column.

2.6 Capture

This explained why my service was taking a long time to start up (because Service Bus was failing to connect via AMQPS and was going through retry cycles before falling back to HTTPS) and also explained why my runtime performance was lower than my expectation (because HTTPS is known to be slower than TCP).  However this didn’t explain why Service Bus was attempting to use port 5671 rather than 9351-9354 as per documentation.

Repeating the same test on my own VM showed that Service Bus was continuing the connection on ports 9351-9354 as expected… So why the difference? On the suggestion of my colleague Mahindra, I compared the assembly versions of the Microsoft.ServiceBus assembly across the two machines. You can do this by running “gacutil -l Microsoft.ServiceBus” in a Visual Studio command prompt, or by manually checking the GAC directory which is typically “C:\Windows\Microsoft.NET\assembly\GAC_MSIL” for .NET 4+ assemblies.

Voila. I found that I was running version 2.1.0.0 on the machine that was behaving correctly, and version 2.6.0.0 on the machine that was misbehaving. It appears that the protocol choosing behavior for Service Bus relays has changed sometime in between these two assembly versions. I have not pinpointed exactly which version this change occurred in, and I don’t yet know whether this change was by design or accidental. Either way, Microsoft have not yet updated their documentation, which means that others will be as confused as I was.

So what are your choices?

  1. You can downgrade to an older version of the assembly.  2.1.0.0 will definitely work for you, but you might be able to get away with a slightly higher version which is less than 2.6.0.0, but it will be up to you to establish which versions are acceptable since I haven’t managed to do this.  You’ll need to update the webHttpRelayBinding binding registration in your machine.config files (or wherever you’ve chosen to register it if you’ve gone for a more granular approach) to point to the older assembly as well.
  2. You can choose to stick with the latest version of the assembly and open up outbound TCP connections on port 5671 on your firewall.

I chose to stick with option #1 because I’m not sure at this stage whether this change in behavior is intentional or incidental, and also because my impression is that raw TCP over ports 9351-9354 would be faster than the AMQPS protocol.  You will find that option #2 is also functional.

With the older version of the assembly in play I could not see traffic on ports 9351-9354 as expected, my services were spinning up in less than a second, and latency was much more in line with my expectations.
2.1 Capture

In a recent post I mentioned how you could dynamically set HTTP headers on a WCF-WebHttp send port.  This post will take this a bit further and discuss how you can dynamically set the target endpoint address as well as the HTTP method.

First things first, just as I mentioned in the post about HTTP headers, you must ensure that the BTS.IsDynamicSend context property is set to true to enable the methods I am about to describe.

Overriding the endpoint address is a piece of cake.  Just set the BTS.OutboundTransportLocation context property to the target URL.

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

        pInMsg.Context.Write("OutboundTransportLocation", "http://schemas.microsoft.com/BizTalk/2003/system-properties", "http://target.service.com/parameters/go/here");
        pInMsg.Context.Write("IsDynamicSend", "http://schemas.microsoft.com/BizTalk/2003/system-properties", true);
        return pInMsg;
    }

Overriding the HTTP method took a bit more trial and error.  In order to achieve this you must set the WCF.HttpMethodAndUrl to the desired HTTP method.

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

        pInMsg.Context.Write("HttpMethodAndUrl", "http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties", "POST");
        pInMsg.Context.Write("IsDynamicSend", "http://schemas.microsoft.com/BizTalk/2003/system-properties", true);
        return pInMsg;
    }

So what exactly does this context property represent and why is it named Method and URL?  This context property represents the value that would normally be contained in the HTTP method and URL mapping section of a WCF-WebHttp send port’s configuration.
MethodAndUrlMapping

If you inspect the help text underneath the textbox in the above screenshot you’ll notice that there are ways to set the HTTP method and URL mapping in this configuration.

  • By hardcoding the HTTP method in the text box such that every message being processed by the send port will have the same HTTP method.
  • By dynamically setting it (and the URL parameters as well) based on the XML BtsHttpUrlMapping configuration based on the value of the BTS.Operation context property on the message being processed.

Whatever value you have in the HTTP method and URL configuration of your send port will be put into the WCF.HttpMethodAndUrl context property on your message before it gets handled by the WCF adapter stack, which will apply the correct HTTP method and outbound URL.

So back to overriding the method, by setting a value to the WCF.HttpMethodAndUrl context property and ensuring that the HTTP method and URL configuration on the send port is blanked out, we are able to dynamically set the HTTP method on the outbound message.

I would be negligent if I didn’t mention that setting these two context properties (and BTS.IsDynamicSend) is a piece of cake when using the BRE Pipeline Framework which has out of the box capabilities to set these context properties. Being rules based, you can inspect the messages that are being processed and dynamically decide what the outbound URL and HTTP method should be based on message content and/or context.
BRE

Theoretically we could even dynamically set the WCF.HttpMethodAndUrl context property value to contain a BtsHttpUrlMapping XML instance so that we could dynamically set the HTTP method and URL based on the BTS.Operation context property value.  Given that it is a lot easier to just set the BTS.OutboundTransportLocation and WCF.HttpMethodAndUrl context properties to set the HTTP method and URL dynamically, this method is just too complicated to have its usage justified in most scenarios.

%d bloggers like this: