Publishing a WCF Service via Service Bus Relay in BizTalk Server 2013 (Part 2)

By Nick Hauenstein

This post is the eighth in a weekly series intended to briefly spotlight those things that you need to know about new features in BizTalk Server 2013. It is also the second part of a two-part series on the Service Bus Relay features in BizTalk Server 2013 (Click here for part 1).

Last week, we examined how BizTalk Server 2013 (and even 2010 in that case) can use the Windows Azure Service Bus Relay to make a service endpoint available in the cloud without otherwise directly exposing the machine, and while being able to take advantage of the claims-based authentication and authorization framework provided by the Access Control Service. This was done in such a way that the service was hosted in IIS rather than within an In Process BizTalk Host Instance. This week, we are going to look at the other side – a service endpoint that is ultimately hosted in IIS.

In this case, we have been provided with a few new adapters to help us along the way (although, if we were really adventurous, WCF-Custom could have still done the trick for us in the past). These two adapters are the WCF-BasicHttpRelay adapter and the WCF-NetTcpRelay adapter:

ServiceBusRelayInProc

Last week, we published a NetTcpRelay endpoint that required some additional work on the client to authenticate with the service. This week, we’re going to go to the other extreme, and publish a WCF-BasicHttpRelay endpoint that will be more or less transparent to the client.

Starting the Game of Telephone

We’re going to start out with the BizTalk version of Hello World, a simple (technically unnecessary, but convenient for illustrative purposes) orchestration. This orchestration receives a simple single node XML message (the single node containing the text “Hello”), and returns a simple single node XML message (containing the word “World”) as the response:

HelloOrch

The Setup

With this, we’re going to go through the typical process of creating an in-process receive location, and then walk through the BizTalk WCF Service Publishing wizard to publish the service. Then we’re going to consume the service as it sits. Once that is complete, we will change up the end point so that it is listening over a Service Bus Relay, and see that the client can still call the service.

We’ll start with the Receive Location. In order to keep this in-process, we’re actually using the WCF-Custom adapter (since WCF-BasicHttp will force us to an Isolated Host):

BasicHttpEP

Now that we have an endpoint to receive messages, we need to create an endpoint that informs clients what messages we’re even interested in – our MEX endpoint. For that, we will go back to the BizTalk WCF Service Publishing wizard, and select the second option – the path less traveled:

MEXPublish_Step1

We will walk through this wizard, ignoring everything that mentions Service Bus publishing for now. Ultimately, what we will end up with is a local endpoint that is exposing the WSDL necessary to consume the service. We can use the svcutil.exe utility to download and share this metadata offline, or even generate proxy classes for re-use later if we’d like. In this case, we will be consuming it in place, and generating a client that can be used to call the service no matter where it lives.

Since we started with an orchestration, and that will define the shape of the incoming/outgoing data, we will select the Publish BizTalk orchestrations as WCF service option. Do note the plural orchestrations in that sentence, I see way too many single operation services out there. Winking smile

MEXPublish_Step3

After browsing for and selecting an orchestration, you should be presented with a list of all public port types within the assembly containing the orchestration. If they Type Modifier property on the Port Type is not set to public, it will not be listed, and you will be sad:

selectport

After you click through a few more screens, you will be prompted for the location where you would like this metadata hosted. In this case, it will be hosted within IIS on the local machine:

MEXPublish_Location

A few more clicks through the wizard, and the MEX endpoint is created and hosted in IIS – though the service endpoint itself is still hosted in-process.

A visit to IIS manage demonstrates that the MEX endpoint is now:

http://localhost/IOServiceMEX/WcfService_QuickLearn_BizTalk_Process.svc?wsdl

Consuming the Service

So far, we haven’t really done anything earth shattering, so consuming the service is equally simple. In this case, I just fired up Visual Studio, used the Add Service Reference context menu option in Solution Explorer, and then provided the MEX endpoint to the wizard. With the (local, not relayed) Service Reference in place, I added the following code to my console app:

[sourcecode language=”csharp”]using System;

namespace QuickLearn.WCF.Client
{
class Program
{
static void Main(string[] args)
{
var client = new IOServiceReference.WcfService_QuickLearn_BizTalk_ProcessClient("BasicHttpBinding_ITwoWayAsync",
"http://localhost:81/Sample/IOService.svc");

var response = client.ProcessMessage(new IOServiceReference.InOutRequest()
{
Contents = "Hello"
});

Console.WriteLine(response.Contents);
Console.ReadLine();
}
}
}[/sourcecode]

 

In the code above, the only moderately odd thing that I did was to use an overload of the client constructor that included an endpoint address. The reason for that was so I could more easily demonstrate the only change necessary as we switch to the WCF-BasicHttpRelay adapter.

To the Cloud

Since my client code is currently working and happy, I am ready to move this to the cloud. I am actually going to maintain my local endpoint (Receive Location) as well and simply add another Receive Location that will open the relay. The configuration of this one will be a little bit different, and certainly more involved.

NOTE: Before you continue, please be sure that you have read part 1.

I’m going to re-use my Azure Service Bus namespace from last week (though I have a new key for this week). I will start by creating a new receive location, selecting the WCF-BasicHttpRelay adapter, and then opening the adapter configuration. The first thing I am prompted for is the listen URI for the endpoint. This URI must incorporate my Service Bus Namespace, and should also add some identifier for the service after:

RelayEP_Config

The only other page of the configuration that I must visit is the Security page. This is where I get to determine if the client needs to provide some sort of authentication information in order to invoke the service, if the existence of the service is going to be discoverable by hitting the root of the namespace, and this is also where I set the authentication details for the access control service – so that BizTalk can prove to Azure that it can listen at that address and receive messages.

Since we don’t want to make changes to our client (other than the endpoint address), we will set the client authentication type to None. Then we need to click Edit under Access Control Service to bring up this dialog:

acs_credentials

In this dialog, we need to re-iterate our namespace (leaving the –sb suffix in-tact), and then then we also need to provide our super secret key which we can look up through the Azure Management Portal (see the previous post for details).

Once that is all in place, we’re set to Enable our Receive Location and then update the client to point to the relay.

Updating the Client

I mentioned before that we really only want to update the endpoint in the client. While this is true, the change of endpoint does (in this case) require a single simple change in configuration. The reason has nothing to do with the Service Bus Relay itself, but instead the change of scheme from http to https. An http address does not imply any security added in by the transport, it is just clear text over the wire. An https address, on the other hand, implies transport level security, as a result we need this small tweak to the otherwise auto-generated config file:

TransportSecurity

And then an update to our endpoint in code (everything else remains):

[sourcecode language=”csharp”]using System;

namespace QuickLearn.WCF.Client
{
class Program
{
static void Main(string[] args)
{
var client = new IOServiceReference.WcfService_QuickLearn_BizTalk_ProcessClient("BasicHttpBinding_ITwoWayAsync",
"https://uniquename.servicebus.windows.net/IOService/");

var response = client.ProcessMessage(new IOServiceReference.InOutRequest()
{
Contents = "Hello"
});

Console.WriteLine(response.Contents);
Console.ReadLine();
}
}
}[/sourcecode]

This gives us the very happy result:

consoleapp_result

Clearly this is one of the most robust, secure, and complex ways to write the word “World” out to the console.

The Take-away

The take-away here for the last two posts is that BizTalk Server 2013 gives you some new options for exposing select endpoints over the internet without touching firewall configuration, without involving IIS (if you don’t want to involve it), and without exposing the whole box out to the internet. All the while giving you the ability to work with clients that are aware of the setup (in the case of the NetTcpRelay) or are blissfully ignorant of the magic behind the scenes (in the case of the BasicHttpRelay).

Publishing a WCF Service via Service Bus Relay in BizTalk Server 2013 (Part 1)

By Nick Hauenstein

This post is the seventh in a weekly series intended to briefly spotlight those things that you need to know about new features in BizTalk Server 2013.

This post will focus on a feature that is technically present in BizTalk Server 2010, but was not installed by default. This feature was a subtle enhancement to the BizTalk WCF Service Publishing Wizard – namely the ability to publish a Windows Azure Service Bus Relay Endpoint without leaving the wizard (and also without using one of the new adapters that has Relay in its title).

Even if you didn’t know that this feature existed, you will find it the first time that you attempt to publish any BizTalk artifact (schema/orchestration) as a WCF service in BizTalk Server 2013. It takes the form of the following screen within the BizTalk WCF Service Publishing Wizard, which appears immediately after choosing to publish a service (rather than simply a metadata description):

publish_sbendpoint

If you check this box and proceed through the wizard (regardless of adapter selected on the first screen), you will see the following screen at the end of the typical wizard:

publish_sbendpoint_part2

The wizard assumes that you have already gone to the Windows Azure Management Portal and created a Service Bus namespace (effectively reserving yourself a sub-domain of servicebus.windows.net, and setting up an access control namespace for claims resolution and authorization purposes). If you’ve never done that before, it can be done through the New menu as shown below:

servicebus_namespace

The next page of the wizard will require information necessary for BizTalk to authenticate with Windows Azure and prove that it is indeed the destination endpoint for the relay. This information is also obtainable only from the Windows Azure Management Portal. In order to access this information, you will need to click on your newly created namespace in the list of Service Bus namespaces, and then click the Connection Information button at the bottom of the page:

connection_info_button

This will bring up the following listing, of which you really only need to worry about the Default Issuer (Issuer Name in the wizard), and Default Key (Issuer Key in the wizard):

connection_info_listing 

Once you gather this information, you’re ready to have a copy/paste party and fill out the last page of the wizard (unless you really want to live life in hard mode, don’t enable client authentication for metadata exchange – if you feel the need to do that, you may as well pass around the raw WSDL to whomever needs it and just forget about a MEX endpoint):

publish_sbendpoint_part3

Once you’re up to this point, you can sprint to the finish by clicking Next, Create (after reviewing the wonderful WSDL and making sure it’s something that you can be proud of), and then finally Finish.

Tackling Common Issues

Outside of the typical issues one might encounter hosting a WCF Service in a BizTalk Isolated Host (e.g., App Pool Identity needs permissions to Message Box database, correct .NET Framework version needs to be selected for App Pool, Receive Location must be started), you may also encounter a new one:

image 

Again, for those using Google-fu in attempt to resolve an error, the error message reads:

Invalid element in configuration. The extension name ‘transportClientEndpointBehavior’ is not registered in the collection at system.serviceModel/extensions/behaviorExtensions

And it’s highlighting the portion of the configuration file that includes the key for Service Bus authentication.

Before getting right to the resolution, let’s recap what we’re looking at. Going through the wizard, I had selected to host a WCF-WSHttp endpoint internally in a BizTalk Isolated Host (i.e., running in an IIS App Pool rather than a BizTalk Host Instance process). I then indicated that I wanted to also expose the service through a NetTcp relay endpoint hosted externally (on Windows Azure).

My local IIS instance has been provided all the configuration information that it needs to coordinate with Windows Azure and make the relay live, but it currently doesn’t know what to do with it – which is why I have the error, and why my relay won’t be alive yet.

In reality, this all could have been avoided by reading. Specifically reading the last page of the BizTalk WCF Service Publishing Wizard, which should tell you that you need to install the AppFabric 1.0 SDK before any of the relays will work. Again, this is functionality that was technically available in the previous generation, hence the older SDK version number.

How to Know That It’s Working

If you have made it this far successfully, hitting the local service endpoint should give you a page that looks something like this:

workingservice

If you go to the Windows Azure Management Portal and dig into the namespace you created, you should see something like this:

relay_azure

It’s Not Real Until I Can Consume It

If you’re anything like me, this is an unsatisfactory ending point – the service doesn’t really exist until I can consume it from some client. To make it as fair as possible, I am hosting the service inside a fairly locked down Windows Azure Virtual Machine, and I will be consuming it from my laptop connected ultimately via a microwave connection somewhere in the shadow of Mt. Pilchuk.

To consume this beast, we need to know our namespace (e.g., unique-name.servicebus.windows.net), and the mex endpoint exposed via relay (seen in the screenshot above). From there I can construct the address I would use in the Add Service Reference dialog in Visual Studio. In this case, that URL will be: https://unique-name.servicebus.windows.net/GetItemServiceDescription/GetItemService.svc_mex

Upon consuming the service, you may notice that the WSDL importer chokes hard on the WSDL it’s finding. It tries to build up a custom binding to make the call, and it’s finding that it doesn’t really know anything about some of the binding elements required:

choked_importer

Again for those searching for this specific error, the message reads:

WsdlImporter encountered unrecognized policy assertions in ServiceDescription ‘YOUR NAMESPACE HERE’

In reality, we don’t need to build a custom binding to make this all happen. Instead, we can use the netTcpRelayBinding to make the connection. An easy way to make that happen is to install the Windows Azure Service Bus NuGet package to our project. We can start out by using the Manage NuGet Packages context menu item in Solution Explorer:

manage_nuget_packages

Then search for the Windows Azure Service Bus package, and click the Install button:

manage_nuget_packages_part2

This should update the App.config file of your application to include the following WCF extensions:

appconfig

From there, you will want to update your endpoint to reference the netTcpRelayBinding (instead of the custom binding that the WSDL importer failed to generate properly):

[sourcecode language=”xml”]
<client>
<endpoint address="sb://YOUR-NAMESPACE.servicebus.windows.net/YOUR-SERVICE-LOCATION/YOUR-SERVICE-HERE.svc"
behaviorConfiguration="sharedSecretClientCredentials" binding="netTcpRelayBinding"
contract="RelayedItemService.ItemService" name="RelayEndpoint" />
</client>
[/sourcecode]

You will also notice above that we have assigned a behaviorConfiguration — one that currently does not yet exist. So next, we will need to add an endpoint behavior (inside the system.serviceModel section of the App.config) to perform client authentication (if you don’t want to re-use the same credentials as before, make that visit over to the ACS Management Portal that the Connection Information page is begging you to do):

[sourcecode language=”xml”]
<behaviors>
<endpointBehaviors>
<behavior name="sharedSecretClientCredentials">
<transportClientEndpointBehavior>
<tokenProvider>
<sharedSecret issuerName="owner" issuerSecret="YOUR SHARED SECRET VALUE HERE" />
</tokenProvider>
</transportClientEndpointBehavior>
</behavior>
</endpointBehaviors>
</behaviors>
[/sourcecode]

This is something that has changed more recently. In fact, I couldn’t find a single place documenting what this behavior should actually look like right now. Hopefully that will change.

Invoking the Service

Once we get through all the configuration craziness, we’re ready to make quick work of calling the service with two lines of code (backed by a billion lines of configuration):

[sourcecode language=”csharp”]
YourServiceDotNetNamespace.YourServiceClient client = new YourServiceDotNetNamespace.YourServiceClient("RelayEndpoint");
client.GetItem(new YourServiceRequest() { Id = "test" });
[/sourcecode]

That’s all it takes.

Final Thoughts

I hope you found some of this helpful. Like I said, this is all technically possible in BizTalk Server 2010, but required additional installation. In BizTalk Server 2013, it is there by default and ready to go (with one tiny SDK install) out of the box.

If you enjoyed this week’s post, then stay tuned. Next week, we will be accomplishing the same tasks with a service hosted in-process in BizTalk Server 2013 using one of the new WCF Relay adapters.