images

In Part 2, you learned how to consume BAM data from orchestration events that were populated by BizTalk. BAM is incredibly powerful when coupled with BizTalk as a message broker and a tool for business choreography. However, one of BAM’s most underutilized and perhaps most useful features is its ability to monitor Windows Communication Foundation services.

One of the chief criticisms of WCF and WF, especially within the .NET Framework 3.5, is the lack of out-of-the-box tools to effectively manage workflow status and the performance of WCF service. Microsoft is expected to address that criticism in its next version of .NET, 4.0, with a set of technologies collectively named “Dublin.”

Rather than waiting for its release and having to perhaps restructure and rewrite your application, BAM and BizTalk 2009 offer the ability to intercept data travelling through services and workflows today.

This chapter will cover

  • Architecture of the interceptors
  • How WCF and BizTalk integrate
  • The syntax of a WCF interceptor file
  • A walkthrough with common IC file examples
  • Configuring the BAM WCF interception
  • Fault handling in the WCF interceptor
  • Loading the WCF interceptor using the BAM API
  • BAM WCF performance counters
  • Hosting and security considerations

This chapter assumes you have basic working knowledge of Windows Communication Foundation, XML, Visual Studio 2008, and BizTalk Server administration.

Architecture of the Interceptors

Before we describe the WCF interceptor, it’s worth stepping back and providing an overview of the way interceptors work.

Interceptor Architecture Overview

One of the advantages that an enterprise server product has over a small desktop application is an architecture with many components and many integration points. Having so many “moving pieces” allows other applications to access the various functionalities offered in the server stack.

However, if you wanted to monitor method invocation and overall health and activity data throughout that stack, adding monitoring mechanisms at multiple points would cause additional latency throughout invocation. In order to provide robust monitoring capabilities, the technology would need to implement a type of “wiretapping” mechanism that would provide the ability to intercept method invocations without interfering with their performance in any way.

As of BizTalk Server 2004, Microsoft introduced the ability to intercept data as it flows through the solution, record date and time information, and look at the actual data as processes are executed. As of BizTalk Server 2006, Microsoft further enhanced that capability to include interception of data as it flows through WCF services and WF workflows.

The interceptors do so by implementing a notification callback mechanism, providing the means to gather the data at various checkpoints, recognize that an interception has occurred, and then record that data within a BAM data store. This intentional design provides high degrees of scalability such that locking is not likely to occur as a result of the interceptor “firing.”

Within a typical BizTalk solution, there exist four major mechanisms through which data flows: adapters, pipelines, maps, and orchestrations (see Figure 8-1). Of these, Microsoft has prebuilt interceptors for each, with the exception of maps. In order to intercept map information, code must be written to send data directly through the interceptor framework APIs. In general, this is not a recommended practice as it tends to “bloat” maps and make them unmanageable. If you must absolutely intercept data as it flows through a map, we recommend using a well-thought-out utility class that encapsulates writing to the BAM API through a BufferedEventStream.

The mechanism through which data flows is referred to as an Event Bus or Event Stream. Data flowing through a pipeline flows through pipeline interceptors in the Messaging Event Bus (MessagingEventStream). Data flowing through orchestrations flows through orchestration interceptors in the Orchestration Event Bus (OrchestrationEventStream). When you utilize the Tracking Profile Editor, you are creating and configuring an interceptor for the Messaging-EventStream and the OrchestrationEventStream.

Adapters, however, differ in that there are only interceptors for WCF and WF, instead of for all adapters. Data flowing through these adapters flows through the Direct Event Bus (DirectEventStream). There are two approaches to intercepting data for a custom adapter. Because the adapter will likely interface with an orchestration, you can use the Tracking Profile Editor and set a port mapping. If you’re rolling your own adapter using a tool like the LOB Adapter Pack, and would like to highly customize your BAM interception, you may do so as well. Deciding where to intercept largely depends upon the design of your application.

Utilizing an interceptor includes two steps: creation and configuration. For messaging and orchestration interception, the Tracking Profile Editor is used to create the interceptors, and set forth a configuration for the pipeline and orchestration interceptors. WCF and WF differ, however, in that the interceptors have already been created. It is the role of the developer to enable and configure that interception, and map it to corresponding activities within the BAM database. Before jumping that far ahead, let’s take a step back to the basics of a WCF service.

images

Figure 8-1. The BizTalk Server 2009 BAM interceptor architecture

The WCF Interceptor

As you’ll recall, a WCF service is typically composed of three layers. All WCF services must implement a ServiceContract and a DataContract. The ServiceContract defines the OperationContracts, or operations, that the service may perform. The Service layer, or ServiceModel, includes the address, binding, contract, and behaviors. The DataContract defines the DataMembers, or data structures, that the service will support. At a lower level, WCF also provides the ability to access the Channel layer, surfacing protocols, transport, and encoding features (see Figure 8-2).

When WCF services are generated, they include both a client proxy and a server dispatcher. The client proxy and server dispatchers are duplicates of one another, and within the individual components include aspects that may be customized (see Figure 8-3).

Because they may be customized and ultimately extended, they also provide the means to gather data for BAM and send it to the BAM data store. Areas for extensibility include services, operations, endpoints, custom bindings, custom encoders, and custom transports.

The WCF interceptor was architected in this way. BizTalk has a custom endpoint behavior implemented using the Parameter Inspector and Message Inspector classes of the WCF service to gather BAM checkpoint data, listen for events as they are fired, and then create the resultant DirectEventStream to send data to the BAM Primary Import tables.

The BAM infrastructure allows WCF services (service dispatchers) or WCF clients (client proxies) to record data against a BAM activity. By attaching itself to a WCF endpoint, the WCF endpoint behavior provides the same level of functionality a traditional MessagingEventStream-based or OrchestrationEventStream-based interceptor does: continuations, document references, and recordation of BAM activity data. When the WCF channel is first opened, the WCF endpoint loads the WCF behavior, and interception begins.

For the WCF Receive adapter, the WCF channel is opened through a class derived from the ServiceHost base class if an in-process BizTalk host is used. When the receive location is started, the channel is opened. If the BizTalk Host is isolated, a ServiceHost factory-derived class opens the WCF channel.

images

Figure 8-2. Communications between a WCF proxy and WCF dispatcher

images

Figure 8-3. Customization points between a WCF proxy and WCF dispatcher

For the WCF Send adapter (the proxies), when a subscription criteria is met for the adapter, the WCF channel is opened. A dynamic ChannelFactory is created and the message(s) are sent out.

The specific WCF endpoint behavior that is attached to the WCF channel may be found within the Microsoft.BizTalk.Interceptors.dll. The DLL includes namespaces for both WCF and WF, and may be found in the Tracking directory of the BizTalk Server 2009 installation. BAMEndPointBehaviorExtension is a class in the DLL that reads from the WCF configuration information in order to create the BAM WCF interceptor, and set the connection string to the BAM Primary Import database as well as the polling interval value to query for new interceptor configurations. The behavior is applied, the interceptor is initialized, and interception continues until the WCF channel is disposed. The WCF interceptor is loaded and configured within either the ApplyClientBehavior or ApplyDispatchBehavior of the WCF framework.

Aside from its data to activity mapping, the IC file must be deployed to the BAM database for a number of other reasons. One of the most important is that the deployment process executed using bm.exe verifies that the manifest set forth in the IC file maps to a valid DLL. Upon initialization of the WCF service, an internal utility, named InterceptorConfiguration-Management, queries the BAM database to retrieve a rowset of interceptor configurations. The results are filtered by technology type: WCF or WF. Because the rowset may contain multiple interceptor configurations, the tracking profile may span multiple WCF services or multiple WF workflows, and multiple BAM activities that use the same .NET assembly containing the ServiceContracts or workflows.

What does this mean to the developer? If you have a service that exposes a ServiceContract, you may have multiple interceptor configurations. Setting the source and the manifest to use is performed using the interceptor configuration EventSource element, as described later in this chapter. It’s important, if not crucial, however, that between multiple deployed IC files the combination of a manifest, event source name, and BAM activity name be unique. Otherwise, you risk having incorrect values written to your BAM activity by other configuration files and their definitions. If you must use the same manifest name between separate IC files, be sure that your event source name is unique. Also try to avoid using the generic contracts whenever possible, if you have control over the definition of the WCF service contract.

Once the interceptor configuration is loaded within the interceptor and initialized, four events within the message inspection occur: BeforeSendRequest and AfterReceiveReply (within the proxy making the outbound call), and BeforeSendReply and AfterReceiveRequest (within the dispatcher providing the reply). A parameter inspection also occurs to validate endpoint names, configurations, operation names, SOAP headers, message contents, SOAP faults that may have occurred, and so on. These validations are made available to the BAM developer using a WCF operation called GetServiceContractCallPoint, which greatly simplifies the many stages of WCF service execution into a simple method that may be called (or in the case of the WCF interceptor, configured). When the argument passed to the method begins with “Service,” the point is within the service or dispatcher. If the argument passed to the method begins with “Client,” the point is within the client or proxy. More details on how to use this method may be found later in the chapter in the section “WCF Operations.”

These tracking points in the execution cycle between the dispatch and proxy may be filtered against in the IC file, meaning an event may be raised at this stage. By setting forth criteria for this event, it may or may not fire. If it does fire, the IC file also provides an action to perform, such as an Update statement to the BAM activity (more on updates later within the chapter in the section “The OnEvent Element”).

Now with an understanding of how the interceptor technology works, let’s dive into how to set it up.

WCF and BizTalk: So Happy Together

It’s important to remember that WCF integrates with BizTalk in three ways: via the adapter, the publication of an orchestration as a WCF service endpoint, and the interceptor.

The WCF adapters provide the capability for BizTalk to communicate with WCF-based applications through the many WCF bindings. BizTalk includes five WCF adapters precon-figured to work with specific bindings: BasicHttpBinding, WsHttpBinding, NetTcpBinding, NetNamedPipeBinding, and NetMsmqBinding. The adapters that correspond to these bindings are the WCF-BasicHttp adapter, WCF-WSHttp adapter, WCF-NetTcp adapter, WCF-NetNamedPipe adapter, and WCF-NetMsmq adapter. BizTalk also includes the WCF-Custom adapter and WCF-CustomIsolated adapter to allow for custom or nondefault binding scenarios. The WCF adapters are used in a scenario when you have created an application that surfaces specific capabilities through a service façade into the application’s data store. When BizTalk must call into that façade layer, the adapter is used. Of these adapters, the WCF-Custom adapter and WCF-CustomIsolated adapter may be used for BAM interception. The remaining adapters, however, do not support adding custom behavior extensions.

The publication of an orchestration as a WCF service is used when the opposite scenario occurs: your application wishes to call into BizTalk and instantiate an orchestration using WCF. The BAM interceptor may be used in this scenario as well: the publication of an orchestration as a WCF service is essentially building a custom adapter. By default, the ability to intercept BAM data travelling through the custom adapter, however, is not enabled. The interception of BAM data is performed using a WCF behavior attached to the WCF service endpoint.

The WCF interceptor provides the capability to support the tracking of data within WCF services, regardless of whether the BizTalk engine is interfacing with them.

In order for the interceptor to work properly, the behavior must be made available to WCF-based adapters. This can be done in multiple files, including app.config and machine. config. Because BAM solutions include executables for the BizTalk engine, tracking and interception, and ServiceHosts for WCF, it is recommended that the BAM interceptor behavior be added at the machine.config level.

EXERCISE 8-1. ADDING THE BAM INTERCEPTOR BEHAVIOR TO THE MACHINE.CONFIG FILE

Adding BAMEndPointBehaviorExtension to the machine.config file will make the extension available for any WCF service on the machine. If you want to expose your orchestration as a WCF service and wish to track either the message data or service calls into the service using BAM, you must follow these three steps:

  1. Create a WCF service using the BizTalk WCF Service Publishing Wizard.
  2. Configure the BizTalk Server receive and send locations and ports using the BizTalk Administration Console.
  3. If hosted within IIS, configure the web service application pool and directory security to provide the proper level of access.

By this point of the book, you should have a basic working knowledge of using BizTalk’s wizards and know how to create a WCF service to expose the orchestration using a binding and corresponding adapter of your choosing. Therefore, this content is not covered here.

EXERCISE 8-2. CONFIGURING RECEIVE AND SEND LOCATIONS AND PORTS FOR BAM WCF INTERCEPTION

The Syntax of a WCF Interceptor File

So now you’ve enabled calls to your orchestration via the WCF Service Publishing Wizard to be intercepted by BAM, or you’ve begun to consider intercepting calls to WCF services that don’t interface with BizTalk. It’s time to define how that message data or calls to services will map to your observation model. That mapping, within WCF and WF, is done by creating an interceptor file.

The interceptor file is based upon XML Schemas stored in the <Installation Path>Microsoft BizTalk Server 2006SDKSamplesBAMInterceptorXSDs directory. These files, CommonInterceptorConfiguration.xsd, WcfInterceptorConfiguration.xsd, and WorkflowInterceptorConfiguration.xsd, are used by the bm.exe utility to validate the configuration file before deployment.

The CommonInterceptorConfiguration schema, shown in Figure 8-4, is shared between both the WCF and WF interceptors, with additional validation specified by the additional schemas. Specific portions of the schema are of great interest when building your IC file.

images

Figure 8-4. The CommonInterceptorConfiguration schema file when opened in Visual Studio 2008

When creating the IC file for your BAM WCF interceptor, it’s important to understand the key portions of the schema. The IC file is not only a means to map data items the service processes to your observation model, but also a definition of how the specific methods within the interceptor should process that data. Five methods of specific interest exist within the code of the WCF interceptor. Rather than having to write code against them, the IC file is a means to map the data input to parameters fed into those methods. The interceptor uses the file to call these methods within the BAM API:

  • BeginActivity(activityName, activityInstance)
  • UpdateActivity(activityName, activityInstance, params object[] data)
  • EndActivity(activityName, activityInstance)
  • EnableContinuation(activityName, activityInstance, continuationToken)
  • AddReference(activityName, activityID, referenceType, referenceName, referenceData, longReferenceData)

imagesnote More information on these methods as well as the BAM API may be found in Chapter 10.

The EventSource Element

The EventSource element specifies the source of the events appearing in the interceptor configuration file. The element includes the three attributes shown in Table 8-1.

images

An example of an EventSource element containing the preceding example would be

<ic:EventSource Name="ProcessingService" Technology="WCF" Manifest="
TopNamespace.SubNameSpace.ContainingClass+NestedClass, MyAssembly, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=d92g5g029353n25"/>

The BAMActivity Element

The BAMActivity element simply defines the name of the BAM activity and is a container for other elements. The element includes only one attribute, listed in Table 8-2.

images

Following is an example of a BAMActivity element containing the preceding example:

<ic:BamActivity Name="Order">
   …
</ic:BamActivity>

The OnEvent Element

The OnEvent element is the heart of the config file definition. It defines a logical event that is mapped to the BAMActivity element that encloses it. The OnEvent element contains four attributes, and these are presented in Table 8-3.

images

Following is an example of an OnEvent element containing the preceding example:

<ic:OnEvent Name="OrderValidation"  Source="ProcessingService"
IsBegin="true" IsEnd="false">
    …
</ic:OnEvent>

The OnEvent element will also include child elements, shown in Table 8-4.

images

images

images

Expression Elements

You may have noticed that the appearance and syntax for Expression elements and their enclosing elements seem a bit strange. That’s because the IC config file uses postfix notation, otherwise referred to as reverse Polish notation (no, we didn’t make that up), or RPN.

The basic principle of RPN is that the operator appears after the operands. As an example, consider adding three to four. In this expression, the operators are the numbers 3 and 4. The operand is plus (+). The traditional arithmetic notation is infix notation, where the operator occurs between the operands. In infix notation, three added to four is represented as 3 + 4. RPN is a postfix notation, where that expression would be represented as 3 4 +. (And before you ask, there’s another notation called prefix or forward Polish notation, where the same expression would be represented as + 3 4.) RPN was widely used with early programmable calculators. Many engineers will be familiar with the classic HP-41C calculator that used RPN.

RPN has two advantages. It makes the syntax for nested expressions very simple, and it’s very easy to implement an RPN expression evaluator. Let’s consider another expression: (3 + 4) * (5 + 6). This expression is equal to 7 * 11 = 77. In traditional infix notation, there’s no way to write this expression without brackets. In RPN, you would write it as 3 4 + 5 6 + *. The way to understand this is to think about how RPN expressions are evaluated. When a number is seen, it is pushed onto the stack. When an operator is seen, it operates on the top two elements of the stack. Table 8-5 breaks the expression 3 4 + 5 6 + * down in terms of the stack contents.

images

Stack-based evaluation makes it very easy to work with complex expressions. In IC files, the RPN expressions are expressed in XML. One operation that’s defined in IC files is the Concatenate operation, which does a string concatenation. Here’s an example of an RPN expression written in XML:

<ic:Expression>
   <ic:Operation Name="Constant">
      <is:Argument>Jeff</ic:Argument>
   </ic:Operation>
   <ic:Operation Name="Constant">
      <is:Argument>Geoff</ic:Argument>
   </ic:Operation>
   <ic:Operation Name="Concatenate" />
</ic:Expression>

This generates the string JeffGeoff. When it is evaluated, the constant “Jeff” is pushed on the stack, the constant “Geoff” is pushed on the stack, and then the two top elements on the stack are evaluated. You’ll see many more examples of RPN later in the chapter.

Data items within the BAM interceptor file come in two flavors: filter expressions and data expressions. Filter expressions expect the result of the RPN expression to be a Boolean value of true or false, while data expressions expect a single value on the stack.

Filter Expressions

Filter expressions evaluate to true or false and are used in WCF or WF interception to detect when a specific event has occurred. In the case of WCF, it’s common to want to get the name of the WCF service endpoint being accessed as well as the operation. Using the WCF operations (covered in the next section), a call to GetEndpointName and GetOperationName would return those values. If the endpoint name returned was CreditCardProcessorService and the operation was ValidateNumber, you could filter the data as

(GetEndpointName = "CreditCardProcessorService") &&
(GetOperationName = "ValidateNumber")

Converting this to RPN yields

GetEndpointName "CreditCardProcessorService" == GetOperationName
"ValidateNumber" == &&

Converting this expression to the equivalent expression for the interceptor configuration file results in the following XML:

<ic:Filter>
  <ic:Expression>
    <wf:Operation Name="GetEndpointName"/>
    <ic:Operation Name="Constant">
      <ic:Argument>CreditCardProcessorService</ic:Argument>
    </ic:Operation>
    <ic:Operation Name="Equals"/>
    <wf:Operation Name="GetOperationName"/>
    <ic:Operation Name="Constant">
      <ic:Argument>ValidateNumber</ic:Argument>
    </ic:Operation>
    <ic:Operation Name="Equals"/>
    <ic:Operation Name="And"/>
  </ic:Expression>
</ic:Filter>
Data Expressions

Data expressions are simply used to define a single string value. A data expression may be defined as any expression that is not enclosed by a Filter element. Data expressions are used by the OnEvent elements CorrelationID, ContinuationToken, Reference, and Update.

Following is an example of a data expression:

<ic:Operation Name="Constant">
      <ic:Argument>Blue</ic:Argument>
</ic:Operation>

Interceptor Operations

Three operation types are utilized when defining an interceptor configuration file: WCF operations, WF operations, and common or shared operations, which are used with both technologies.

Shared Operations

Table 8-6 lists the four operations that are exposed to both the WCF and WF interceptors to be used within your filter expressions:

<ic:Filter>
  <ic:Expression>

</ic:Expression>
</ic:Filter>

images

WCF Operations

The WCF Interceptor provides six operations, listed in Table 8-7, to extend filter and updating capabilities within an interceptor configuration file.

images

images

A Walkthrough with Common IC File Examples

There are a number of common scenarios found in IC files. You may have noticed that certain methods tend to be called more often than others. In general, writing an IC file can be broken down into four repeatable steps:

  1. Define the event source; that is, what general name you are going to refer to the event source as, which technology it uses (WCF or WF), and what manifest is to be used as the event source.
  2. Define the BAM activity, that is, what activity you are defining to view in the BAM Portal or what your consuming application is. Remember to make this unique and specific to your scenario.
  3. Define the event or events, that is, on which event or events in the client/proxy processing cycle you want to want to perform some action.
  4. Define your actions to perform, that is, whether you want to update data in the BAM activity or utilize continuations, correlations, or references.

Let’s walk through a couple common examples of building IC files.

Example 1: Sales and Fulfillment by Region

Because WCF services are oftentimes exposed using SOAP and XML, the XPath capabilities of the WCF interceptor may be considered invaluable.

The AWO Corporation allows its sales force in the field to create orders on their laptops for customers while disconnected, and then, when near an access point, submit the XML-based orders to a WCF service. Orders are fulfilled in several regional manufacturing centers in the following geographic regions: Northeast, Middle Atlantic, Southeast, Central, South, Northwest, and Southwest. A customer submitting an order in the Northeast may or may not have his or her order fulfilled there. The selection of the region to fulfill the orders is based upon a number of factors, including local labor costs (regional unions, average wage per employee, etc.), regional transportation costs (diesel fuel, highway taxes, etc.), and availability of raw materials in the region.

The AWO Logistics group has devised numerous calculations that will derive the most cost-effective region in which to fulfill the order, and has been tasked with identifying order patterns and developing techniques to reduce long-term costs for AWO. Long-term costs may be reduced by having the correct number of trucks at a facility rather than having to drive them from a nearby facility, thus increasing costs; or by examining regional fuel costs and attempting to maximize the amount of goods to be shipped in a truck.

The Logistics group approaches IT and asks that from each order the following data be captured and made available to its members via a Logistics BAM Portal: CustomerName, CustomerRegion, ItemName, ItemQuantity, ItemWeight, OrderDate, and DeliveryDate.

Fortunately, the sales catalog made available on each salesperson’s laptop includes those data points. An excerpt of the XML order message is as follows:

<?xml version="1.0" encoding="utf- 8"?>
 <order id="A6242966-BB0E-48f6-B654-1D3321AC2C77">
  <history>
   <creation>
    <dateTime>20090801 14:02:30 EST</dateTime>
    <user>Babe</user>
   </creation>
   <lastNodified>
    <dateTime>20090815 01:08:35 EST </dateTime>
    <user>Porky</user>
   </lastModified>
   <estimatedDelivery>
    <dateTime>20090817 12:00:00 EST</dateTime>
    <promissor>Piggy, Ms.</promissor>
   </estimatedDelivery>
   …
  </history>
  <customer id="B38CE334-8527-4b06-B81A- 60397C1C696F">
   <name>Petunia Pig</name>
   <salesRegionId>4</salesRegionId>
   …
  </customer>
  <manifest>
   <item  id="C18028DB-D7B7-4a35-A3E2-CF2FA7E14A1E">
    <name>Porcus Home Wrap – 20 ft. roll</name>
    <quantity>5</quantity>
    <description>Protects your structure from the elements.</description>
    <dimensions>
     <weightQuantity>50</weightQuantity>
     <weightUoM>kg</weightUoM>
    </dimensions>
    …
   </item>
  </manifest>
 </order>
</xml>

Now that we have what we need, let’s build the IC file.

First, let’s start out with the basics of the file, and then create the event source. We start with the document declaration and namespace reference for WCF interception.

<?xml version="1.0" encoding="utf- 8"?>
<ic:InterceptorConfiguration xmlns:ic="http://schemas.microsoft.com/BizTalkServer/
2004/10/BAM/InterceptorConfiguration" xmlns:wcf="http://schemas.microsoft.com/
BizTalkServer/2004/10/BAM/WcfInterceptorConfiguration" >

Next, we define the event source. In this case, it’s the order processing service exposed by AWO.

  <ic:EventSource Name="AWOOrderProcessingServiceSource" Technology="WCF"
Manifest="AWOServices.IProcessOrders, AWOServices, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null">
    <wcf:NamespaceMappings>
      <wcf:Namespace Prefix ="order" Uri="http://tempuri.org/"/>
      <wcf:Namespace Prefix="s"  Uri="http://www.w3.org/2003/05/soap- envelope" />
    </wcf:NamespaceMappings>
 </ic:EventSource>

Then we create the activity we wish to define in BAM and our observation model.

<ic:BamActivity Name="OrdersProcessingByRegion">

We next define an event to be raised (condition to be met). Because our activity is self-contained, IsBegin and IsEnd can be set to true. We set Source to our event source defined previously.

<ic:OnEvent IsBegin="true" IsEnd ="true" Name ="Create"
Source="AWOOrderProcessingServiceSource">

Now that we have our container for the event, we have to actually provide the condition to be met using a Filter element. Each order makes a request to a WCF service, specifically, to the ProcessOrder method. Knowing that, we can decide to use the GetServiceContractCall-Point operation to make sure we’re examining each request to the service, but also limit it to only requests made to the ProcessOrder method by using GetOperationName. We have two criteria: GetServiceContractCallPoint = "ServiceRequest", and GetOperationName = "ProcessOrder". Using RPN, the logic would look something like this:

GetServiceContractCallPoint
ServiceRequest
Equals
GetOperationName
ProcessOrder
Equals
And

Formatting this as XML, we get the following:

<ic:Filter>
   <ic:Expression>
     <wcf:Operation Name="GetServiceContractCallPoint" />
     <ic:Operation Name="Constant">
       <ic:Argument>ServiceRequest</ic:Argument>
     </ic:Operation>
     <ic:Operation Name="Equals" />
     <wcf:Operation Name="GetOperationName" />
     <ic:Operation Name="Constant">
       <ic:Argument>ProcessOrder</ic:Argument>
     </ic:Operation>
     <ic:Operation Name="Equals" />
     <ic:Operation Name="And" />
   </ic:Expression>
 </ic:Filter>

Let’s consider any correlation or continuation needs. We need to identify a correlation token. In our case, the Logistics department will drive its business needs off of the SalesRegionId. The business activity will be driven based upon this value, so it makes sense for us to set it up as a correlation token.

<ic:CorrelationID>
    <ic:Expression>
      <wcf:Operation Name ="XPath">
        <wcf:Argument>//salesRegionId</wcf:Argument>
      </wcf:Operation>
    </ic:Expression>
  </ic:CorrelationID>

Lastly, we need to update BAM with the information that the Logistics department requested. The exact names the department requested were not found in the XML, so we’ll have to do some simple mapping using Update statements to retrieve and map. For each data item, we need to create a separate update node, as follows:

<ic:Update DataItemName="CustomerName" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//customer/name</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="CustomerRegion" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//customer/salesRegionId</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="ItemName" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/name</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="ItemQuantity" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/quantity</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="ItemWeight" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/dimensions/weightQuantity</wcf:Argument>
          </wcf:Operation>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/dimensions/weightUoM</wcf:Argument>
          </wcf:Operation>
          <ic:Operation Name="Concatenate" />
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="OrderDate" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//order/history/creation/dateTime</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="DeliveryDate" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//order/history/estimatedDelivery/dateTime</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>

Note that we aggregated the two weight values together to provide Logistics with an easy-to-read value with context. Lastly, we have to close all of the tags:

    </ic:OnEvent>
  </ic:BamActivity>
</ic:InterceptorConfiguration>

The final IC file is as follows:

<?xml version="1.0"  encoding="utf- 8"?>
<ic:InterceptorConfiguration xmlns:ic="http://schemas.microsoft.com/
BizTalkServer/2004/10/BAM/InterceptorConfiguration"
xmlns:wcf="http://schemas.microsoft.com/BizTalkServer/2004/10/
BAM/WcfInterceptorConfiguration" >
  <ic:EventSource Name="AWOOrderProcessingServiceSource" Technology="WCF"
Manifest="AWOServices.IProcessOrders, AWOServices, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null">
    <wcf:NamespaceMappings>
      <wcf:Namespace Prefix ="order" Uri="http://tempuri.org/"/>
      <wcf:Namespace Prefix="s"  Uri="http://www.w3.org/2003/05/soap- envelope" />
    </wcf:NamespaceMappings>
  </ic:EventSource>
  <ic:BamActivity Name="OrdersProcessingByRegion">
    <ic:OnEvent IsBegin="true" IsEnd ="true" Name ="Create"
       Source="AWOOrderProcessingServiceSource">
      <ic:Filter>
        <ic:Expression>
          <wcf:Operation Name="GetServiceContractCallPoint" />
          <ic:Operation Name="Constant">
            <ic:Argument>ServiceRequest</ic:Argument>
          </ic:Operation>
          <ic:Operation Name="Equals" />
          <wcf:Operation Name="GetOperationName" />
          <ic:Operation Name="Constant">
            <ic:Argument>ProcessOrder</ic:Argument>
          </ic:Operation>
          <ic:Operation Name="Equals" />
          <ic:Operation Name="And" />
        </ic:Expression>
      </ic:Filter>
      <ic:CorrelationID>
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//salesRegionId</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:CorrelationID>
      <ic:Update DataItemName="CustomerName" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//customer/name</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="CustomerRegion" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//customer/salesRegionId</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="ItemName" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/name</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="ItemQuantity" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/quantity</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="ItemWeight" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/dimensions/weightQuantity</wcf:Argument>
          </wcf:Operation>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//item/dimensions/weightUoM</wcf:Argument>
          </wcf:Operation>
          <ic:Operation Name="Concatenate" />
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="OrderDate" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//order/history/creation/dateTime</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
      <ic:Update DataItemName="DeliveryDate" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//order/history/estimatedDelivery/dateTime</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>
    </ic:OnEvent>
  </ic:BamActivity>
</ic:InterceptorConfiguration>

Example 2: WCF Service Usage

As simple as it sounds, a common and prevalent usage of BAM with WCF is to determine use of the service or methods the service offers. Versioning of publicly exposed WCF services can be a challenge: you create a service to perform some processing, and after some time, realize that additional features or capabilities need inclusion. Because service contracts are explicit, by changing the contract, you risk compatibility issues. Many times during the service life cycle, a developer must decide whether the new service or operation should deprecate the older functionality.

As a sample scenario, consider a credit card processing service. At one time, transactions online simply involved providing the name and number of the cardholder. Over time, as numbers were recorded in databases that were later compromised by malicious code, credit cards numbers found their way into the hands of hackers. As such, financial institutions began inclusion of a three-or four-digit security code on the back of each card, as well as the billing postal code of the cardholder.

In this scenario, a WCF service previously existed with a C# method signature as follows:

[OperationContract]
public bool Validate(string cardNumber, string cardholderName,
DateTime expirationDateTime);

After the financial institutions introduced the requirement to also include the security code and billing postal code, a new method was introduced, with the following signature:

[OperationContract]
public bool ValidateSecure(string cardNumber, string cardholderName, DateTime
expirationDateTime, int securityCode, string billingPostalCode);

Members of IT Operations want to know whether there are any callers to the Validate method so that they may set a date by which the older method will be no longer be supported based upon usage, and create additional revenue via an “extended support” model.

To create an IC file for this scenario, we begin with the document and namespace declarations:

<?xml version="1.0" encoding="utf- 8"?>
<ic:InterceptorConfiguration xmlns:ic="http://schemas.microsoft.com/
BizTalkServer/2004/10/BAM/InterceptorConfiguration"
xmlns:wcf="http://schemas.microsoft.com/BizTalkServer/2004/
10/BAM/WcfInterceptorConfiguration" >

Next, we define the event source. In this case, it’s the credit card validation service.

  <ic:EventSource Name="CardValidationServiceSource" Technology="WCF"
Manifest="AWOServices.IValidateCards, AWOServices, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null">
    <wcf:NamespaceMappings>
      <wcf:Namespace Prefix ="card" Uri="http://tempuri.org/"/>
      <wcf:Namespace Prefix="s"  Uri="http://www.w3.org/2003/05/soap- envelope" />
    </wcf:NamespaceMappings>
  </ic:EventSource>

Then we create the activity we wish to define in BAM and our observation model.

<ic:BamActivity Name="CallsToDeprecatedService">

We next define the event to be raised. The activity is self-contained, so IsBegin and IsEnd can be set to true. We set Source to our event source defined previously.

<ic:OnEvent IsBegin="true" IsEnd ="true" Name ="ValidateCall" Source="
CardValidationServiceSource ">

Next, we provide the condition to be met using a Filter element. We need to use two methods, Validate and ValidateSecure. Simply enough, we’re looking for any requests to the service (ServiceRequest) where the method being called is the deprecated method, Validate. Again, we use the GetServiceContractCallPoint operation to make sure we’re examining each request to the service, and limit it to only requests made to the Validate method by using GetOperationName. We have two criteria: GetServiceContractCallPoint = "ServiceRequest" and GetOperationName = "Validate". Using RPN, the logic would look something like this:

GetServiceContractCallPoint
ServiceRequest
Equals
GetOperationName
Validate
Equals
And

Formatting this as XML, we get the following:

<ic:Filter>
  <ic:Expression>
    <wcf:Operation Name="GetServiceContractCallPoint" />
    <ic:Operation Name="Constant">
      <ic:Argument>ServiceRequest</ic:Argument>
    </ic:Operation>
    <ic:Operation Name="Equals" />
    <wcf:Operation Name="GetOperationName" />
    <ic:Operation Name="Constant">
      <ic:Argument>Validate</ic:Argument>
    </ic:Operation>
    <ic:Operation Name="Equals" />
    <ic:Operation Name="And" />
  </ic:Expression>
</ic:Filter>

There’s no real need here to correlate information between requests or activities. Once a single call is made, IT Operations has no intent of keeping a record of which card numbers or postal codes were sent, just that the service was called. As such, we can autogenerate a correlation token like this:

<ic:CorrelationID>
  <ic:Expression>
    <wcf:Operation Name="AutoGenerateCorrelationToken"/>
  </ic:Expression>
</ic:CorrelationID>

Next, we create the action to perform, an Update block, to track the call and record the date and time of the call:

<ic:Update DataItemName ="ValidateMethodRequestInstance" Type ="DATETIME">
  <ic:Expression>
    <wcf:Operation Name ="GetContextProperty">
     <wcf:Argument>EventTime</wcf:Argument>
    </wcf:Operation>
  </ic:Expression>
</ic:Update>

Finally, we close our tags.

</ic:OnEvent>
  </ic:BamActivity>
</ic:InterceptorConfiguration>

The final IC file is as follows:

<?xml version="1.0"  encoding="utf- 8"?>
<ic:InterceptorConfiguration xmlns:ic="http://schemas.microsoft.com/
BizTalkServer/2004/10/BAM/InterceptorConfiguration"
xmlns:wcf="http://schemas.microsoft.com/BizTalkServer/2004/
10/BAM/WcfInterceptorConfiguration" >
<ic:EventSource Name="CardValidationServiceSource" Technology="WCF"
Manifest="AWOServices.IValidateCards, AWOServices, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null">
    <wcf:NamespaceMappings>
      <wcf:Namespace Prefix ="card" Uri="http://tempuri.org/"/>
      <wcf:Namespace Prefix="s" Uri="http://www.w3.org/2003/05/soap- envelope" />
    </wcf:NamespaceMappings>
  </ic:EventSource>
<ic:BamActivity Name="CallsToDeprecatedService">
<ic:OnEvent IsBegin="true" IsEnd ="true" Name ="ValidateCall" Source="
CardValidationServiceSource ">
     <ic:Filter>
        <ic:Expression>
          <wcf:Operation Name="GetServiceContractCallPoint" />
          <ic:Operation Name="Constant">
            <ic:Argument>ServiceRequest</ic:Argument>
          </ic:Operation>
          <ic:Operation Name="Equals" />
          <wcf:Operation Name="GetOperationName" />
          <ic:Operation Name="Constant">
            <ic:Argument>Validate</ic:Argument>
          </ic:Operation>
          <ic:Operation Name="Equals" />
          <ic:Operation Name="And" />
        </ic:Expression>
      </ic:Filter>
<ic:CorrelationID>
  <ic:Expression>
    <wcf:Operation Name="AutoGenerateCorrelationToken"/>
  </ic:Expression>
</ic:CorrelationID>
<ic:Update DataItemName ="ValidateMethodRequestInstance" Type ="DATETIME">
  <ic:Expression>
    <wcf:Operation Name ="GetContextProperty">
     <wcf:Argument>EventTime</wcf:Argument>
    </wcf:Operation>
  </ic:Expression>
</ic:Update>
</ic:OnEvent>
  </ic:BamActivity>
</ic:InterceptorConfiguration>

Configuring the BAM WCF Interception

Chapter 3 provides end-to-end coverage of how to configure WCF for interception and how to capture data from a WCF service external to BizTalk. By this point, you should have enabled the machine.config file, set the necessary send and receive ports and locations, and written an IC file that will provide the observation model you desire.

Fault Handling WCF Interception

In the event an exception occurs during the processing of a WCF request or response, the default behavior for WCF is not to return that exception to the client unless it is thrown as a FaultException (or inherited subtype) or if a FaultContract is implemented. It’s important to consider fault handling in the context of the interceptor insomuch that as the number of activities grows and your BAM infrastructure monitors multiple systems, you’ll have less time to track down individual errors as they occur. It is of paramount importance to develop a fault-handling strategy from the beginning.

Fortunately, BAM and the interceptor configuration file provide a means for doing so. The GetServiceContractCallPoint method includes the ability to pass a Constant argument as an argument representing the fault track point (e.g., ServiceFault, ClientFault, CallbackFault) and map to the point of a specific update action within the message to execute.

Unfortunately, there are limitations to this implementation due to the way in which WCF returns faults, specifically during the ServiceFault and ClientFault track points. In fact, the fault-handling strategy for the IC file is largely dependent upon how the WCF service handles faults itself. Provided you have captured the fault as part of your WCF response, you may use XPath to retrieve the fault and update it in your BAM activity.

The IC file with comments for such an approach follows:

<!-- Define an event that will populate your BAM Activity  //-- >
<ic:OnEvent IsBegin ="true" IsEnd="false" Name="AuthorizationServiceReply"
Source="ESCreditCardService">

<!-- This block filters on the fault track point ServiceReply, and on the
ValidateCreditCard method being invocated. //-- >
<!-- When a ServiceReply occurs for method invocation, the filter will fire.  //-- >
  <ic:Filter>
    <ic:Expression>
      <wcf:Operation Name="GetServiceContractCallPoint"/>
      <ic:Operation Name ="Constant">
        <ic:Argument>ServiceReply</ic:Argument>
      </ic:Operation>
      <ic:Operation Name ="Equals"/>
      <wcf:Operation Name="GetOperationName" />
      <ic:Operation Name="Constant">
        <ic:Argument>ValidateCreditCard</ic:Argument>
      </ic:Operation>
      <ic:Operation Name ="Equals" />
      <ic:Operation Name ="And" />
    </ic:Expression>
  </ic:Filter>

<!-- This block is added to create a correlation token between the request and
the reply  //-- >
  <ic:CorrelationID>
    <ic:Expression>
      <wcf:Operation Name="AutoGenerateCorrelationToken"/>
    </ic:Expression>
  </ic:CorrelationID>

<!-- If a reply has occurred to the ValidateCreditCard operation at the
ServiceReply fault track point, mark the "Status" of the BAM Activity as
"Success" //-- >
  <ic:Update DataItemName="Status" Type="NVARCHAR">
    <ic:Expression>
      <ic:Operation Name="Constant">
        <ic:Argument>Success</ic:Argument>
      </ic:Operation>
    </ic:Expression>
  </ic:Update>

<!-- If a reply has occurred to the ValidateCreditCard operation at the
ServiceReply fault track point, set the "Result" of the BAM Activity to
the value returned by the XPath expression provided below within the WCF
response message //-- >
  <ic:Update DataItemName="Result" Type="NVARCHAR">
    <ic:Expression>
      <wcf:Operation Name ="XPath">
        <wcf:Argument>//s:Body/CreditCardService:*/CreditCardService: ValidateCreditCardResult</wcf:Argument>
      </wcf:Operation>
    </ic:Expression>
  </ic:Update>

<!-- If a reply has occurred to the ValidateCreditCard operation at the
ServiceReply fault track point, set the "Service Call Date" of the
BAM Activity to the current date and time  //-- >
  <ic:Update DataItemName ="Service Call Date" Type ="DATETIME">
    <ic:Expression>
      <wcf:Operation Name ="GetContextProperty">
        <wcf:Argument>EventTime</wcf:Argument>
      </wcf:Operation>
    </ic:Expression>
  </ic:Update>

</ic:OnEvent>

<!-- If you wish, define another event that will populate your BAM Activity //>
<ic:OnEvent IsBegin ="true" IsEnd="false" Name="AuthorizationServiceFault"
Source="ESCreditCardService">

<!-- This block filters on the fault track point ServiceFault, and on
the ValidateCreditCard method being invocated.  //-- >
<!-- When a Service Fault occurs for method invocation, the filter will fire.  //-- >
   <ic:Filter>
    <ic:Expression>
      <wcf:Operation Name="GetServiceContractCallPoint"/>
      <ic:Operation Name ="Constant">
        <ic:Argument>ServiceFault</ic:Argument>
      </ic:Operation>
      <ic:Operation Name ="Equals"/>
      <wcf:Operation Name="GetOperationName" />
      <ic:Operation Name="Constant">
        <ic:Argument>ValidateCreditCard</ic:Argument>
      </ic:Operation>
      <ic:Operation Name ="Equals" />
      <ic:Operation Name ="And" />
    </ic:Expression>
  </ic:Filter>

<!-- This block is added to create a correlation token between the request
and the reply //-- >
  <ic:CorrelationID>
    <ic:Expression>
      <wcf:Operation Name="AutoGenerateCorrelationToken"/>
    </ic:Expression>
  </ic:CorrelationID>

<!-- If a fault has occurred to the ValidateCreditCard operation at
the ServiceFault fault track point, mark the "Status" of the BAM Activity as
"Fault"  //-- >
  <ic:Update DataItemName="Status" Type="NVARCHAR">
    <ic:Expression>
      <ic:Operation Name="Constant">
        <ic:Argument>Fault</ic:Argument>
      </ic:Operation>
    </ic:Expression>
  </ic:Update>

<!-- If a fault has occurred to the ValidateCreditCard operation at the
ServiceFault fault track point, mark the "Source" of the BAM Activity as
the value returned by the XPath expression provided below within the WCF
response message within Reason/Text //-->
      <ic:Update DataItemName="Source" Type="NVARCHAR">
        <ic:Expression>
          <wcf:Operation Name ="XPath">
            <wcf:Argument>//s:Body/Fault/Reason/Text</wcf:Argument>
          </wcf:Operation>
        </ic:Expression>
      </ic:Update>

<!-- If a fault has occurred to the ValidateCreditCard operation at
the ServiceFault fault track point, mark the "Service Call Date" of the
BAM Activity to the current date/time //-- >
  <ic:Update DataItemName ="Service Call Date" Type ="DATETIME">
    <ic:Expression>
      <wcf:Operation Name ="GetContextProperty">
        <wcf:Argument>EventTime</wcf:Argument>
      </wcf:Operation>
    </ic:Expression>
  </ic:Update>

</ic:OnEvent>

Loading the WCF Interceptor Using the BAM API

While Chapter 10 more comprehensively covers the BAM API, we felt it important to cover manual loading of the BAM interceptors in this chapter.

While it’s not common, in some scenarios you would want to load the WCF interceptor using the BAM API rather than using a configuration file. Values within the config file, especially those in Filter elements or within Update elements, are static. Therefore, if you would like to change the values of the tracking profile on-the-fly, or if you would prefer to call your own methods against which to compare constants, you’ll need to load the WCF interceptor manually using the BAM API.

The SDK utilizes the following (corrected) code to load the BAM interceptors using the BAM API. However, there are many ways in which this may be done. The BAM API, while largely undocumented, does include a great deal of functionality for interfacing with BAM via the API. More information on the BAM API may be found in Chapter 10.

In the code that actually opens the service, add a reference to the Microsoft.BizTalk. Interceptors.dll and add a using statement to Microsoft.BizTalk.Interceptors.Wcf. Add the following code:

   internal class MyBamBehaviorExtension : BamBehaviorExtension
    {
        internal MyBamBehaviorExtension(string connectionString,
           int pollingInterval)
            : base()
        {
            this.PrimaryImportConnectionString = connectionString;
            this.PollingIntervalSec = pollingInterval.ToString();
        }

        internal IEndpointBehavior Create()
        {
            return (IEndpointBehavior) this.CreateBehavior();
        }
    }

Within the code that executes just before the service is actually opened, include the following code to add the endpoint behavior to the service:

MyBamBehaviorExtension bamBehaviorExtension =
new MyBamBehaviorExtension(ConfigurationManager.AppSettings["ConnectionString"],
int.Parse(ConfigurationManager.AppSettings["PollingIntervalSec"]));
        IEndpointBehavior bamBehavior = bamBehaviorExtension.Create();
        foreach (ServiceEndpoint endpoint in myServiceHost.Description.Endpoints)
        {
            if (endpoint.Behaviors.Find<MyBamBehaviorExtension>() == null)           endpoint.Behaviors.Add(bamBehavior);
        }

This code also assumes that you are reading the ConnectionString value from the config file.

BAM Interceptor Performance Counters

There are six performance counters that are of interest to BAM WCF developers. These performance counters enable you to not only monitor performance, but also identify bottlenecks for your BAM WCF implementation. While a wiretapping pattern incurs negligible degradation, it is still helpful to have the counters to identify where activities may need to be restructured, or when calls to a WCF service are taking too long as a result of the binding endpoint behavior.

All of these performance counters, listed in Table 8-8, may be accessed by examining the performance counter category “BAM Interceptor.”

images

Hosting and Security Considerations

When considering the many “moving pieces” in a solution that involves SQL Server, IIS, WCF, BAM, and the file system, it’s clear that security and hosting options play a key role in the health of the overall solution.

The security roles you use when intercepting the WCF adapter are the same as those used for other BAM solutions. The additional considerations for intercepting the WCF adapter involve selecting the correct user and event writer role to use.

When using WCF services and the WCF adapter, all BAM-related data is written to the BAM Primary Import database by the selected role.

You can select the proper user role configuration by assessing your solution scenario. If your solution requires many new services that are tracked by many different activities and are all run under the same user account, it is advantageous to use the BAM event writer super role to write the intercepted events.

imagesNote Users must be added to the BAM event writer super role. When adding a user to the super role, it is important to remember that the user will then be able to write to all the activities in the system.

If your solution requires greater control of the events written, you should use activity-specific roles.

imagesNote Users must be added to the activity-specific event writer role for each activity.

Summary

In this chapter, we covered the architecture of the interceptors, diving into the implementation details, and then specifying the implementation for WCF. This chapter also covered the three ways that BizTalk and WCF integrate and went through an extensive (and hopefully exhaustive) coverage of the interceptor configuration file syntax. The chapter included fault-handling techniques within the WCF interceptor, as well as a code sample and a scenario on when and how to load the WCF interceptor programmatically. The chapter finished with tips on when to use each BAM performance counter and hosting and security considerations.

The next chapter will build upon the information provided in this chapter, covering how the BAM WF interceptor may be used to intercept data within WF workflows.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.170.206