SOA Patterns with BizTalk Server 2013 and Microsoft Azure(Second Edition)
上QQ阅读APP看书,第一时间看更新

Consuming WCF services from orchestrations

For BizTalk Server to play a full role within the service bus, it must be able to not only expose service endpoints but also easily consume them. Let's take a look at how to create an orchestration that accepts messages through the WCF-NetTcp receive location created earlier and also calls a WCF service that reveals a single endpoint based on Named Pipes.

We start by adding a new orchestration file named LookupOrderContact.odx to our existing BizTalk project in Visual Studio. The orchestration starts up when a new order arrives. Therefore, we should create a new orchestration message of type BizTalkSOA.Chapter3.OrderManagement.BizTalk.NewOrder_XML, named NewOrder_Input. After the order is received, we call an existing WCF service, which provides us with more details about the customer placing the order. What do we need to know to call the WCF service from our orchestration? If you guessed the following, you'd be right:

  • Schema contract(s) used
  • Message exchange pattern (request/reply, request only)
  • Service address and binding

Instead of having to manually produce these artifacts and configurations, we should use BizTalk-provided tools to do the work for us. If you wanted to reference a WCF service from a standard Visual Studio project (for example, class library, ASP.NET application), you could use the Add Service Reference option available by right-clicking on the project. However, adding WCF references to BizTalk projects works a bit differently.

First let's start by off creating a running service with a WCF-NetNamedPipe endpoint and an explicit MEX endpoint by starting a command prompt (Run as Administrator) and browsing to the BizTalkSOA.Chapter3.OrderService\bin\Release folder in the accompanying source code and running BizTalkSOA.Chapter3.OrderService.exe. It should come up with Order service host opened….

To add a WCF service reference, first right-click on the BizTalk project and choose Add and then Add Generated Items. We are presented with a window that Visual Studio uses to auto-construct BizTalk artifacts, such as schemas based on adapter endpoints. Choose the Consume WCF Service option and click on Add.

Now we get the pleasure of working with the BizTalk WCF Service Consuming wizard. This is a twin of the BizTalk WCF Service Publishing Wizard, except that instead of generating new services, it produces the artifacts necessary to consume existing ones.

The first thing the wizard has to find out is where to get the metadata needed to craft the artifacts for BizTalk. If you only have a physical XSD and WSDL file (assuming someone went the true contract-first design route), then the second option in the wizard (Metadata Files) is best. However, if the target service is live and allows metadata queries, we can choose the first option.

After choosing Metadata Exchange Endpoint as the metadata source, we plug in the address of the metadata URL. In my case, this value is net.pipe://localhost/BizTalkSOA.Chapter3.OrderService/mex. Note that while only http(s) endpoints actually produce browsable metadata, any WCF endpoint can still expose metadata to query.

On the next screen of the wizard (assuming that our service was accessible), we see a summary of what the wizard is about to import.

A number of files are generated, including three different XSD schemas. These schemas describe the data types contained in the service contract. We also get two BizTalk binding files: one for the adapter type used in the metadata request (in our case, WCF-NetNamedPipe) and another we can optionally use to configure a WCF-Custom send port. In addition, the wizard emitted a new orchestration, which contains type definitions for multi-part messages representing the contract schemas and a port type that reflects the message exchange pattern of the target service.

Back in our primary orchestration, we now add the messages used for calling the service and handling the response. These messages (Contact_Request and Contact_Response) are created by using the multi-part message types defined in the wizard-generated orchestration.

The service input message is represented as a complex (schema) type, so a BizTalk map is necessary to instantiate the new orchestration message. This means our orchestration requires a Construct shape in concert with a Transform shape that points to a new map. The map is quite simple as all we need to do is transfer the data in the target schema's PhysicianID XML node to the destination schema's contactId node.

Once the map is finished, we add the Send and Receive shapes to the orchestration. The orchestration will send the request message and receive the response message. Once the shapes are dropped on the orchestration, and the corresponding Message properties are set on them, we create the logical port used by the orchestration to communicate with the service. After choosing to create and name a New Configured Port, we want to choose an existing port type for this port.

On the next screen of the wizard, we confirm that the direction of the port is set to send a message and receive a response. We should now connect the service's send and receive shapes with the connectors on the logical port operation. Our final shape in the orchestration should be an Expression shape, where a success confirmation is printed. If we want to extract data from the response message as proof that the response was successfully received, then we need to distinguish a field within the service response schema. In my case, I distinguished the Name element and printed that value out. To complete the orchestration, I added a new logical receive port for accepting the inbound order. The finished orchestration looks like this:

After deploying the orchestration, we have a few remaining tasks to perform from inside the BizTalk Administration Console.

  1. First, the generated BizTalk binding file should be imported so that our WCF send port is created automatically for us. Importing a binding is done by right-clicking the BizTalk application (in our case, named BizTalkSOA.Chapter3) and choosing Import and then Bindings.
  2. Point this dialog box to the adapter-based binding (in our case, named ContactService.BindingInfo.xml) instead of the custom binding.
  3. After the import succeeds, we see a new (un-enlisted) send port that utilizes the WCF-NetNamedPipes adapter. That port should be turned on by right-clicking on it and choosing Start.
  4. Our final step is to bind and enlist the orchestration. We created a one-way WCF-NetTcp receive channel in the previous exercise and can reuse that receive port as our input to the orchestration. The orchestration binding is represented as follows:

Once we start the orchestration and ensure that the downstream service is up-and-running, we should trigger our client service. From the following screenshot, you can see that the client succeeded; the downstream service registered an invocation, and the orchestration successfully sent a trace message to the application Event Log.