I've been playing lately with a few WCF features as well as with the WCF Adapter in BizTalk Server 2006 R2. As part of that I had a need to set up a receive location using one of the WCF HTTP-based bindings.

Normally, this isn't a big deal; you can easily use the BizTalk WCF Service Publishing Wizard to create the receive location and IIS service application for an orchestration or from a set of BizTalk schemas.

However, this time I did not want to go that way. What I really wanted was just a simple receive location that would simply receive messages and submit them over to BizTalk without tying the receive location to a specific service definition. As far as I could see, the Service Publishing Wizard didn't really have an option for this, but I was confident it could be made to work.

To be honest, I did have a set of schemas I wanted to work with and even a bunch of predefined WSDL files. However, for many reasons (including the sheer complexity of the schemas and WSDL files involved) I didn't want to get that involved in my initial BizTalk message receiver and processor.

Fortunately, turns out that doing what I wanted was fairly easy stuff. In fact, it was so easy that was able to leverage an existing service I had previously created. I basically just copied the .SVC file (and renamed it) alongside the web.config file. I explicitly ignored all the stuff that normally gets generated under the App_Data directory.

I then manually created a matching receive location in BizTalk using the WCF-BasicHTTP adapter, and this worked right away perfectly for my needs!

Just in case you've never looked at what a WCF HTTP receive location generated files look like, it's actually fairly simple stuff. The SVC file contains just a single directive as expected:

<%@ ServiceHost Language="c#" Factory="Microsoft.BizTalk.Adapter.Wcf.Runtime.BasicHttpWebServiceHostFactory, Microsoft.BizTalk.Adapter.Wcf.Runtime, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

You can see here that it references the WCF-BasicHTTP adapter. If you wanted to use, say, the WCF-WSHttp Adapter, then you'd use Microsoft.BizTalk.Adapter.Wcf.Runtime.WSHttpWebServiceHostFactory class instead.

The config file is pretty much the default config file generated by the Service Publishing Wizard as well:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   <configSections>
      <section 
         name="bizTalkSettings" 
         type="Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkConfigurationSection,
            Microsoft.BizTalk.Adapter.Wcf.Runtime, Version=3.0.1.0,
            Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
   </configSections>
   <bizTalkSettings>
      <mexServiceHostFactory debug="false">
         <receiveLocationMappings>
            <!--add markupFileName="*.svc"
               receiveLocationName="?"
               publicBaseAddress="protocol://host[:port]" /-->
         </receiveLocationMappings>
      </mexServiceHostFactory>
      <webServiceHostFactory debug="false" />
      <isolatedReceiver disable="false" />
      <btsWsdlExporter disable="false" />
   </bizTalkSettings>
   <appSettings />
   <connectionStrings />
   <system.web>
      <compilation defaultLanguage="c#" debug="false">
         <assemblies>
            <add assembly="mscorlib, version=2.0.0.0, culture=neutral,
          60;     publickeytoken=b77a5c561934e089" />
            <add assembly="Microsoft.BizTalk.Adapter.Wcf.Common, Version=3.0.1.0,
               Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="Microsoft.BizTalk.Adapter.Wcf.Runtime, Version=3.0.1.0,
               Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
         </assemblies>
      </compilation>
      <authentication mode="Windows" />
   </system.web>
   <system.serviceModel>
      <behaviors>
         <serviceBehaviors>
            <behavior name="ServiceBehaviorConfiguration">
               <serviceDebug 
                  httpHelpPageEnabled="true" 
                  httpsHelpPageEnabled="false" 
                  includeExceptionDetailInFaults="false" />
               <serviceMetadata 
                  httpGetEnabled="false" 
                  httpsGetEnabled="false" />
            </behavior>
         </serviceBehaviors>
      </behaviors>
      <services>
         <service 
            name="Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkServiceInstance" 
            behaviorConfiguration="ServiceBehaviorConfiguration">
            <!--<endpoint
               name="HttpMexEndpoint"
               address="mex"
               binding="mexHttpBinding"
               bindingConfiguration=""
               contract="IMetadataExchange" />-->
            <!--<endpoint
               name="HttpsMexEndpoint"
               address="mex"
               binding="mexHttpsBinding"
               bindingConfiguration=""
               contract="IMetadataExchange" />-->
         </service>
      </services>
   </system.serviceModel>
</configuration>

It's extremely nice to see how the WCF adapter in BizTalk leverages a bunch of my favorite features in WCF to make this a lot simpler (compared to, say, the whole bunch of code that neede d to be generated for the original SOAP adapter).

I should mention though, that part of what made it so easy was that my needs were pretty simple: I wanted a simple two-way (request/response) port, and needed no metadata (WSDL) publishing at all (as I said, I already had working WSDL files I could provide to consumers of the service).  Making it one-way wouldn't have been a problem though; as the WCF adapter handles it very gracefully as well.

Technorati tags: ,