BizTalk Send Ports, WS-Addressing, ClientVia and non-http prefixed To headers, Part 2

In a previous post I explained how we had a need to use the WS-Addressing To header to send a non-http prefixed URI, such as urn:company/path/subpath/Service1, and how that was supported, after a fashion, out of the box in BizTalk Server. It did however come with the limitation of not being able to edit the WCF config in the BizTalk Server Administration Console GUI once you loaded it from a binding file. I don’t like limitations.

In this post I’ll show you how you can create a very simple WCF behavior to help you to set a RemoteAddress EndpointAddress Uri to be able to accomplish the same thing, while still being able to continue to edit the port configuration.

WCF behaviors allows you to intercept and inspect or alter messages or metadata, or in other ways modify the runtime behavior or processing of the same as they are sent or received. In this case we are creating a client behavior.

The behavior is in essence very very simple, it’s only purpose is to alter the endpoint address at runtime. The place where I choose to implement this is in the ApplyClientBehavior method of the IEndpointBehavior interface.

void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
{
    serviceEndpoint.Address = new System.ServiceModel.EndpointAddress(this.Uri);
}

Incidently, I borrowed this implementation with pride from the ClientVia behavior that comes with the .NET Framework. Apart from the fact that that behaviors sets the ClientRuntime.Via property and this sets the ServiceEndpoint.Address property the implementation is very close to exactly the same.

This allows you to configure BizTalk in the following manner.

The “Address (URI)” property can be set to anything (as long as it is http or https prefixed), since it will later be overridden.

In the behaviors section we now have two behaviors, clientVia:

and the new one I created, which I called remoteAddress:

clientVia is configured as the actual URI of the service we need to call, while the remoteAddress behaviors is configured with the value we want to have in the To header.

The solution contain three files of interest.

The App.config file holds a snippet of configuration that needs to be placed in machine.config or in the BizTalk WCF-Custom WCF extension part of the Send Handler of the host that handles the WCF calls being made. It exists to make the behavior available to the BizTalk process and looks like this:

<extensions>
  <behaviorExtensions>
    <add name="remoteAddress" type="bLogical.BizTalk.WSAHelper.RemoteAddressElement, bLogical.BizTalk.WSAHelper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3672865486d21857"/>
  </behaviorExtensions>
</extensions>

It points to the RemoteAddressElement class, whose responsibility it is to point out the type of the behavior and create new instances.

The RemoteAddressBehavior then in turn does the already above explained logic.

The project and code is available here.

I suppose a custom pipeline component setting the Address, or a Dynamic Send port for easier cases of configuration might also do the trick.

Blog Post by: Johan Hedberg

BizTalk Send Ports, WS-Addressing, ClientVia and non-http prefixed To headers

Through WS-Addressing services can require a certain value in the ws-addressing <wsa:to> SOAP header. WCF has full support for this. This support is inherited by the WCF-Adapters. When using WS-addressing in a BizTalk Server Send Port what you enter in the “Address (URI)” of the WCF adapters configuration will also be the value that ends up in the <to> header.

Like so:

 

This will produce the following. Other headers and body removed for clarity.

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:To s:mustUnderstand="1">http://localhost:8990/Service1</a:To>
  </s:Header>
  <s:Body>
    ...
  </s:Body>
</s:Envelope>

If you need to have a different value in the <to> header than the actual address that the service is hosted at it becomes a little bit trickier. You need to use the WCF-Custom adapter and add the ClientVia behavior. The value configured as the “Address (URI)” will still end up as the value in the <to> header, but the actual URI that the call will be made to will be the value you configure in the ClientVia’s viaUri property.

Like so:

 

This will produce the following (again cleaned for clarity):

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:To s:mustUnderstand="1">http://somedummyvalue/</a:To>
  </s:Header>
  <s:Body>
    ...
  </s:Body>
</s:Envelope>

Now, as long as the value that you want in the <to> header is http or https (depending on the bindings security settings) then you are fine. However, if you end up needing to have a value in your <to> header that looks for example like this: urn:company/path/subpath/Service1, then you’re in trouble.

You will get an error dialog saying that The specified address is invalid. Invalid address scheme; expecting “http” scheme.

Why? Because BizTalk Server in its diligence to help you configure things correctly will force you to enter an URI that is prefixed with either http or https (again, depending on the security setting of the binding). There is no way for you to configure a non-http prefixed port in the adapter GUI (that I know of).

A colleague of mine, Gustav Granlund, experienced this issue and found a solution: you can coup it in through a binding file, and the runtime will accept it. Doing this you can enter a “Address (URI)” like so:

And you are then able to send a message that looks like this (to an address of http://localhost:8990/Service1):

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:To s:mustUnderstand="1">urn:company/path/subpath/Service1</a:To>
  </s:Header>
  <s:Body>
    ...
  </s:Body>
</s:Envelope>

The caveat is that after having done this you cannot open and change WCF adapter settings in the port through the administration console GUI and keep the urn:company/path/subpath/service1 style URI. But, as mentioned, BizTalk will happily run with it. In a follow up post I examine another option.

HTH,

/Johan

Blog Post by: Johan Hedberg

Working with BAM BizTalk 2013

Working with BAM BizTalk 2013

This space is to describe my experience working with BAM on BizTalk 2013 using SQL Server 2012. Business Activity Monitoring (BAM) provides real-time business intelligence by capturing data as it flows through a business system. By using BAM, we monitor a business process in real time and generate alerts when the business process needs human […]
Blog Post by: shadabanwer

Using key file authentication with the BizTalk SFTP adapter

Using key file authentication with the BizTalk SFTP adapter

Authentication on an SFTP location can be done with simple username/password credentials… However another way to authenticate the sender is by using a Key Authentication file. But how can this last authentication method be used inside the BizTalk SFTP adapter? the BizTalk SFTP adapter we used to achieve this is the freely available SFTP adapter […]
Blog Post by: Cnext

BizTalk: REST getting nice URLs with IIS Url Rewrite

“Ding ding” after spending 4 rounds(hours) in the ring with this guy, I’m taking the
gloves off and heading for the showers and salts.

I’m in the middle of some BizTalk work (which is nice for a change) and I’m ticking
my tasks off.

I’ve got a REST receive port exposed from BizTalk via IIS and published through the
WCF Publishing Wizard.

(there’s Operations mappings and extracting variables from the URL to Context Properties
under the Configure – omitted for brevity)

Couple of shots of the WCF Service Publishing Wizard:

The issue here is that – once the Wizard completes you’ll get:

http://<servername>/coreapi/customer/Service1.svc as the URL
to call.

The task was simple:

I wanted to call URLs such as

http://<servername>/coreapi/customer/123456789/enquire

http://<servername>/coreapi/customer/123456789/verify

etc. 

And not their equivalents of:

http://<servername>/coreapi/customer/Service1.svc/123456789/enquire

 

The Solution was to use IIS URL Rewrite which looks to be the Swiss
Army knife that MacGuyver uses.. (but he only needs a paperclip to take out an entire
train).

Lots of samples and numerous examples of solutions that work and people are high-fiving
in about 5 mins of startingalas not for me .
The other point to note here also is that a URL Rewrite module exists
for:

  • Default Web Site
  • Each IIS Application under the Root Website.

I wanted to keep things confined to just my IIS Application and not have to have requirements
of changing the Default Web Site for instance.

The tricky part was to find out how IIS works and it’s matching.

Underneath CoreApi I have Customer as an Application
as in

/coreapi/customer

**The part that URL Rewrite appears to do** (that floored me for a while)

It chunks the FULL REQUEST and passes just the part required to your app.

So take the full URL:

http://localhost/coreapi/customer/1234234/enquire

As you traverse down the IIS ’Application tree’ the URL that is passed to each URL
Rewrite in each underlying IIS Application is *different*, as in:

  • /coreapi = ’customer/1234234/enquire’
  • /coreapi/customer = ’1234234/enquire’

This was possibly the hardest piece to figure out. I’d setup failed request tracing
in IIS and those logs, while I feel like I’m walking into the Engineering room of
the century with all the logs, pages and info I wasn’t seeing ’URL Rewrite failed
to apply your rule because ..’  – it just wasn’t appearing plain and simple.

URL Rewrite – the rules that won the show

  1. Under /coreapi/customer in IIS Manager
  2. Started off with a Blank Rule and setup the following:

    >

    So the RegEx Rule (at this level) simply states – if the Request begins with a number,
    then prepend ’Service1.svc/’ to it.

    The key is knowing what the URL being passed to URL Rewrite is at this level in the
    IIS Application/vdir tree.

    What the web.config says at this level:

    <rewrite>
               <rules>
                  
    <rule name=”CoreApi Rule” patternSyntax=”ECMAScript”>
                      
    <match url=”([0-9].*)” />
                      
    <action type=”Rewrite” url=”Service1.svc/{R:1}” appendQueryString=”false” logRewrittenUrl=”true”
    />
                  
    </rule>
               </rules>
           </rewrite>

    I hope I’ve saved you a bit of time on your next endeavour.

    Blog Post by: Mick Badran

Publishing ASP.NET Web Sites to “Windows Azure Web Sites” Service

Publishing ASP.NET Web Sites to “Windows Azure Web Sites” Service

Today, Microsoft made a number of nice updates to their Visual Studio tools and templates. On thing pointed out in Scott Hanselman’s blog post about it (and Scott Guthrie’s post as well), was the update that lets developers publish ASP.NET Web Site projects to WIndows Azure Web Sites. Given that I haven’t messed around with […]
Blog Post by: Richard Seroter

Android Date Time Picker Dialog

While looking for the best way to implement an input widget to retrieve the users’s Date of Birth I came across this input field while editing a contacts information in the generic People List that comes with the Android OS:

When pressed this opens the DatePickerDialog as shown below:

The Android SDK provides a DatePickerDialog which (as […]
Blog Post by: Nick Rubino