官术网_书友最值得收藏!

Consuming WCF services without orchestration

There are plenty of scenarios where orchestration is an unnecessary addition to service bus processing. Recall that an orchestration's prime benefit is the injection of a stateful, sequential series of steps to message processing. If the "processing" of a message can consist solely of the core BizTalk messaging components (receive ports, send ports, pipelines, maps, and subscriptions), then a messaging-only solution is the way to go. A general rule among BizTalk architects is that you avoid orchestration and concentrate on pure messaging when at all possible. This isn't because orchestration is intrinsically bad but rather because many situations actually don't require the overhead and complexity of a workflow.

That said, how nicely does the BizTalk bus play with WCF services when no orchestration is involved? Quite well, thank you. Let's look at how we may route inbound data to a WCF subscriber using only the message bus.

In our new scenario, we have a target service in our enterprise resource planning (ERP) system that accepts new order notices and uses WCF's WsHttpBinding. We'd like to call this service whenever a new product order enters the MessageBox. This subscriber does not need any direct knowledge of the upstream publisher or how the message arrived to the bus.

  1. We start this example by referencing the target service from within Visual Studio. This is done by once again right-clicking the BizTalk project and choosing Add and then Add Generated Items.
  2. The Consume WCF Service is selected, and when the BizTalk WCF Service Consuming wizard launches, the Metadata Exchange Endpoint is picked as the source of the service metadata.
  3. Now we plug in the valid HTTP endpoint URI of our WCF service:

When the wizard completes, we have a set of metadata files (schemas, bindings, and orchestrations) that help describe the service and how to consume it. This example doesn't use orchestration, but we do still require one hand-built BizTalk artifact—a map. The WCF service expects the order data to be in a particular format, so we should design a map that gets applied by the outbound send port. The BizTalk map takes the repeating set of order items and puts them into their appropriate fields in the target schema.

Now we build and deploy our updated project. Once that deployment has succeeded, we import the binding generated by the BizTalk WCF Service Consuming wizard. For this scenario:

  1. Let's import the custom binding (OrderService_Custom.BindingInfo.xml) so that we can see the different properties this adapter exposes.
  2. A send port is created for the WCF-Custom adapter, but note that the binding specified by the adapter matches that of our service endpoint, wsHttpBinding.

On the General tab of the adapter configuration, observe that there is a section called SOAP action header. This contains the SOAP action that will be attached to the outbound messages for this send port.

The BtsActionMapping wrapper in this textbox is used to support multiple SOAPAction values. However, this also means that something needs to set the BTS.Operation value, which the WCF adapter uses to choose the appropriate SOAP action from this collection. Typically, this is set by the orchestration's logical send port operation name, but in the absence of an orchestration, we would have to set the BTS.Operation value in a custom pipeline component. Before throwing up your hands and swearing loudly at this unnecessary complexity, breathe deeply and relax. Luckily, this textbox also supports an alternate format that is more supportive of simple content-based routing scenarios. A single SOAP action URI in this textbox is used when you want to apply the same SOAPAction header to all messages transmitted by the send port. For our scenario, let's switch this to the single SOAPAction header that corresponds to our target service operation.

Next, we must apply our XSLT map to this send port. The map is a required component because our service is expecting a very specific data format that does not match the original structure of the data.

Our final step is to introduce a valid subscription for this send port. Without one, this port will never receive any messages published to the bus. Because we'd like to pull every order from the MessageBox, our subscription should be type-based, not context-based. A context-based subscription would say that we are subscribing to properties of the message (for example, which port it arrived at) instead of anything relating to the message itself. We want to subscribe to all messages of a particular type. The subscription applied can be seen in the following screenshot:

Now, technically we are finished. If we send a message into BizTalk, it should route to a listening send port and produce the expected tracing statements. However, see the following Pitfall to resolve an error with our current configuration.

Note

Pitfall

The solution, as it stands now, will raise an exception. Why? The WCF service that BizTalk calls does not return a response message. However, the auto-generated BizTalk binding file was for a two-way send port. So, when the WCF service is called, the request is successful but we end up with a subscription not found exception on the (empty) response message. We can fix this by creating a new one-way send port with configuration settings (adapter type, URI, binding, SOAPAction, and subscription) identical to those of the auto-generated port.

主站蜘蛛池模板: 玉林市| 阳原县| 巴彦县| 唐河县| 饶阳县| 玉龙| 竹北市| 尚志市| 横山县| 莱西市| 兴城市| 哈巴河县| 吉木乃县| 宁津县| 山丹县| 明水县| 昭平县| 同仁县| 汽车| 舒城县| 砚山县| 白沙| 临城县| 如皋市| 平远县| 区。| 东方市| 临夏市| 开化县| 梁河县| 乐亭县| 化州市| 祁阳县| 岱山县| 巍山| 杭锦后旗| 宁城县| 崇礼县| 龙州县| 田阳县| 灵寿县|