Export (0) Print
Expand All

Orchestrating XML Web Services and Using the Microsoft .NET Framework with Microsoft BizTalk Server

 

Ulrich Roxburgh
Microsoft Corporation

February 2002

Applies to:
    Microsoft® .NET Framework
    Microsoft BizTalk™ Server
    Microsoft Visual Studio® .NET

Summary: How to deploy scalable, highly available XML Web services using BizTalk Orchestration and the .NET Framework. (33 printed pages)

Contents

Introduction
BizTalk Server and the .NET Framework
BizTalk Orchestration and XML Web Services
BizTalk Messaging and XML Web Services
Extending BizTalk Server with .NET
Other BizTalk Server Development with the .NET Framework
Acknowledgements

Introduction

An XML Web service is programmable application logic that is accessible using standard Internet protocols. XML Web services combine the best aspects of component-based development and the World Wide Web. Like components, XML Web services represent black-box functionality that can be reused without regard to how the service is implemented. In Microsoft® BizTalk™ Server, XML Web services can be implemented using Microsoft SOAP Toolkit 2.0 and Microsoft Visual Studio® .NET.

BizTalk Orchestration introduces some remarkable synergies for the application developer who wants to deploy scalable, highly available Web services. BizTalk Orchestration provides a long-running, loosely coupled business process that includes implementation services, such as transactions—both Microsoft Distributed Transaction Coordinator (DTC)-style transactions, and timed and long-running transactions—exception handling, and transaction compensation, to enable the application designer to create robust business processes. A BizTalk Server Orchestration is a process created in the Microsoft Visio®-based BizTalk Orchestration Designer, serialized in XML, and executed under the control of COM+ services (called XLANG Scheduler).

The most obvious way to extend BizTalk Server with .NET technology is to develop extensions to BizTalk Server using Visual Studio .NET. BizTalk Server provides an application integration framework that is simple, yet extensible and flexible. This framework takes the form of application integration components (AICs), two types of which are supported by BizTalk Server: AICs supporting the BTSAppIntegration interface and pipeline component AICs.

When building applications using Visual Studio .NET, there are two common mechanisms to submit documents to BizTalk Server from these applications: submitting directly, using the IInterchange interface, and submitting by writing the document to a Message Queuing (also known as MSMQ) message for BizTalk Server to pick up using a Message Queuing receive function.

BizTalk Server and the .NET Framework

BizTalk Server is part of the Microsoft Windows Server System. BizTalk Server provides two core functions:

  • Message-level integration, from the enterprise (enterprise application integration, or EAI) to the Internet (business-to-business, or B2B), through BizTalk Server Messaging.
  • Business process automation using BizTalk Server Orchestration services, which provide the ability to implement long-running, loosely coupled business processes.

BizTalk Server is built on, and integrates closely with, the Component Object Model (COM). You can extend BizTalk Server Messaging by using COM to create application integration components (AICs), pre-processors, and custom parsers and serializers. Similarly, the implementation of actions in a BizTalk Server orchestration is typically based on COM components. The COM extensions for both BizTalk Messaging and BizTalk Orchestration are currently built using a COM-compliant language, such as Microsoft Visual Basic® or Microsoft Visual C++®.

The Microsoft .NET Framework is a new platform for building integrated, service-oriented applications to meet the needs of today's Internet businesses: applications that gather information from, and interact with, a wide variety of sources, regardless of the platforms or languages in use. The larger Microsoft .NET initiative envisions software services on the Web. The key principle of the .NET initiative is that a new kind of application, called an "XML Web service" will become the engine for business over the Internet. Parts of this vision are shared with other key players in the industry.

Leveraging off the .NET Framework, Visual Studio .NET is a complete set of development tools for building:

  • ASP.NET applications
  • XML Web-based services
  • Desktop applications
  • Mobile applications

Visual Studio .NET provides an integrated development environment (IDE), which is shared by Visual Basic .NET, Visual C++ .NET, and Microsoft Visual C#™ .NET. Visual Studio .NET provides access to key technologies that simplify the development of these sophisticated applications.

Integrating BizTalk Server with the .NET Framework (in particular XML Web services and Visual Studio .NET) provides considerable benefit for the application developer. BizTalk Server provides significant support for the development of applications that are widely distributed in space (EAI and B2B) and time (long-running business processes). Visual Studio .NET is a much richer IDE than any previous developer tool, with many more services and facilities available to the application developer.

This white paper examines how BizTalk Server integrates with the .NET Framework architecture and Visual Studio .NET. It discusses how BizTalk Server can access available XML Web services, how BizTalk Server functionality can be used to construct XML Web services, and how Visual Studio .NET can be used to access and extend BizTalk Server.

XML Web Services, WSDL, and SOAP

An XML Web service is programmable application logic that is accessible using standard Internet protocols. XML Web services combine the best aspects of component-based development and the World Wide Web. Like components, XML Web services represent black-box functionality that can be reused without regard to how the service is implemented. Unlike previous component technologies, XML Web services are not accessed through object model-specific protocols, such as the distributed Component Object Model (DCOM), Remote Method Invocation (RMI), or Internet Inter-ORB Protocol (IIOP).

Instead, XML Web services are accessed through ubiquitous Web protocols and data formats, such as Hypertext Transfer Protocol (HTTP), Extensible Markup Language (XML), and SOAP. Furthermore, an XML Web service interface is defined strictly in terms of the messages the Web service accepts and generates. Consumers of an XML Web service can be implemented on any platform in any programming language, provided they can create and consume the messages defined for the XML Web service interface.

Building or consuming XML Web services involves specifications and technologies that address five requirements for service-based development:

  • A standard way to represent data
  • A common, extensible message format
  • A common, extensible service-description language
  • A way to discover services located on a particular Web site
  • A way to discover service providers

XML is the obvious choice for a standard way to represent data related to XML Web services (the format of the data transmitted to and from the Web service). As such, the various Web service-related specifications all use XML for data representation.

XML Web services require a messaging protocol that can invoke the Web services and exchange data with them. SOAP is a lightweight, XML-based protocol for exchanging information in a decentralized, distributed environment. SOAP is a network protocol, with no underlying explicit programming model. Because SOAP does not mandate the technology used to implement the client or server applications, it requires no application programming interface (API) or object model. As such, SOAP provides an open methodology—XML Web services—for application-to-application communication.

WSDL

The Web service honors a contract with its clients regarding the messages it accepts and generates. To support this, Microsoft and IBM jointly developed an XML-based contract language, called Web Services Description Language (WSDL), as a standard mechanism for creating and interpreting Web service contracts. WSDL is used to create a file that identifies the services and the set of operations within each service that the server supports. The WSDL file also describes the format that the client must follow in requesting an operation. WSDL is analogous to the Interface Definition Language (IDL) for COM components.

Web service clients need to be able to discover where Web services are located. The Discovery Protocol (Disco) specification defines a discovery document format based on XML, and a protocol for retrieving the discovery document, enabling developers to discover services at a known URL. However, in many cases the developer will not know the URLs where services can be found. Universal Description, Discovery, and Integration (UDDI) specifies an advertising mechanism for Web service providers, and a location device for Web service consumers.

SOAP operation types

The operations in the WSDL file are defined by the style attribute of the <soap:binding> element in the file, and can be one of the following:

  • Document-oriented operations. If an operation in the WSDL file is document-oriented, the input (request) and output (response) messages specified for that operation contain XML documents.
  • RPC-oriented operations. RPC-oriented operations have input messages that contain the operation's input parameters and output messages that contain the operation's results.

Implementing XML Web Services Using SOAP Toolkit

Many systems created for Microsoft platforms are based on COM. Microsoft SOAP Toolkit 2.0 provides both high-level and low-level components for creating and consuming XML Web services by COM-based applications. These components include:

  • A client-side component that enables an application to invoke Web service operations described by a WSDL document.
  • A server-side component that maps invoked Web service operations to COM object method calls as described by the WSDL and XML Web Services Meta Language (WSML) files.
  • Necessary components that construct, transmit, read, and process SOAP messages. These processes are collectively referred to as marshalling and unmarshalling.

In addition, SOAP Toolkit 2.0 provides additional tools that simplify the development of XML Web services and client applications:

  • A WSDL/WSML Generator tool that generates the WSDL and WSML files.
  • The SOAP Messaging Object (SMO) framework, which is an alternative to using the XML DOM API to process XML documents in SOAP messages. The SMO framework is a Microsoft Visual Basic add-in that generates message part objects that simplify the creation and processing of XML documents contained in SOAP messages.

The following steps describe how to build a simple Web service based on a COM component named SOAPDemo.Calculator using the Add method.

  1. Start the WSDL Generator. This is used to generate the WSDL and WSML files that describe the SOAP service, and how that service will be implemented.
  2. Load a COM component dynamic-link library (DLL) that you have previously built. In this example, SOAPDemo.dll is used. The WSDL Generator will read the type library of the DLL to determine the methods that can be exposed as XML Web services.

    Ee251575.bts_wp_net_01(en-US,BTS.10).gif

    Figure 1. Running the SOAP Toolkit Wizard

  3. The SOAP Wizard generates either an ISAPI- or ASP-based listener, which will listen for SOAP requests, parse them, instantiate the COM object, and call the appropriate method on the COM object, passing in the parameters that are sent in the SOAP request. (The ISAPI listener is recommended because of its performance characteristics.)
  4. The SOAP Toolkit Wizard generates the WSDL and WSML files for the Web service into the folder specified. After the SOAP Toolkit Wizard finishes, this folder is shared as a Web folder, so that clients can access the WSDL and WSML file through HTTP.

Implementing XML Web Services Using Visual Studio .NET

Visual Studio .NET natively provides extensive XML Web services functionality. XML Web services can be created in Visual Basic, Visual C#, or Visual C++.

To create a Web service using Visual Studio .NET:

  1. Start a new project, and select ASP .NET Web Service to build a Web service using either Visual C# or Visual Basic, or select Managed C++ Web Service to build a Web service using Visual C++.
  2. Enter a name for the Web service and a location at which the Web service will be deployed, then click OK to generate the Web service project.
  3. Visual Studio .NET creates a project (in your language of choice) that imports the namespaces System.Web.Services and System.Web.Services.Protocols, and adds a class that is derived from System.Web.Services.XML Web services. This class will implement the Web service.
    Imports System.Web.Services
    Imports System.Web.Services.Protocols
    
    Public Class Account
    Inherits System.Web.Services.WebService
    
    
  4. Add methods to the class that implement the various Web methods. In this case, we have created methods to debit, credit, and check a customer's credit in real time at the customer's bank. To designate the method as an XML Web service, simply prepend each method with a WebMethod attribute.
    <WebMethod()> Public Function CheckCredit(_
    ByRef AccountNo As Integer, _
    ByRef AmountToDebit As Integer) As Integer
    
    

    Ee251575.bts_wp_net_02(en-US,BTS.10).gif

    Figure 2. Browsing the ASMX file, showing the methods exposed by the Web service

  5. When the project is built, it will create a XML Web service on the specified Web server, which exposes each method that has a WebMethod attribute.
  6. Information about the Web service—such as the WSDL file—can be obtained by browsing to the .asmx file for the class that implements the XML Web service:

    http://localhost/BankVBNet/BankVBNet.asmx

BizTalk Orchestration and XML Web Services

XML Web services are a key enabling technology for the Microsoft vision of providing great software, any time, any place, and on any device. XML Web services enable a code reuse pattern by which services are made available to an application without being physically co-located. However, this disconnected scenario offers some significant challenges:

  • Interaction among XML Web services. XML Web services provide simplified access to both local and remote business logic. However, an application that is composed of many XML Web services introduces a management challenge: How are the interactions between and across the aggregated XML Web services managed in an agile manner so that new XML Web services can be readily added to an application?
  • Transaction management and exception handling. Aggregated XML Web services provide access to remote business logic, but how can transactions be managed across XML Web services? Also, how can exception processing be provided that requires different XML Web services to be called?
  • Concurrency. Applications should be able to call XML Web services with no inter-dependencies—such as an XML Web service that checks inventory and one that checks a customer's credit—in a parallel manner. How can this be achieved without complex threading issues?
  • Interaction with non-XML applications. Application development today involves equal interaction with XML Web services and applications that are not XML Web service-enabled. How can interactions be managed across both types of systems in a homogeneous manner?

In many cases, it is not possible to use a simple synchronous invocation model for Web services in the way COM object invocation is handled.

BizTalk Orchestration introduces some remarkable synergies for the application developer who wants to deploy scalable, highly available Web services. BizTalk Orchestration provides a long-running, loosely coupled business process that includes implementation services, such as transactions—both Microsoft Distributed Transaction Coordinator (DTC)-style transactions, and timed and long-running transactions—exception handling, and transaction compensation, to enable the application designer to create robust business processes.

Many requirements that have driven the need for these facilities are also found in loosely coupled XML Web services. BizTalk Orchestration provides significant benefits to the application designer building highly distributed, long-running processes. The following section, Calling XML Web Services from an Orchestration Schedule, discusses how XML Web services can be combined with BizTalk Orchestration, both by orchestrations calling XML Web services to implement specific actions within those orchestrations, and by XML Web services being implemented using a BizTalk Orchestration.

Calling XML Web Services from an Orchestration Schedule

BizTalk Orchestration Designer provides the following implementation shapes that represent technologies that can be used to implement port communications:

  • COM Component. Each port is implemented by using a method call for each message that is sent or received to a COM+ component or a .NET component using COM Interop.
  • Script Component. Each port is implemented by using a method call for each message that is sent or received to a script component.
  • Message Queuing. Each port is implemented by sending to or receiving from a message queue.
  • BizTalk Messaging. Each port is implemented by sending to or receiving from BizTalk Messaging Services.

Ee251575.bts_wp_net_03(en-US,BTS.10).gif

Figure 3. The four implementation shapes in BizTalk Orchestration Designer

XML Web services, however, are invoked by sending SOAP-formatted requests to the Web service and receiving SOAP-formatted responses back to the client. The easiest way to implement this from a BizTalk Orchestration schedule is by calling a COM or .NET component, which invokes the Web service using SOAP. In effect, the COM component acts as a proxy for the Web service. The COM component proxy can be created using either SOAP Toolkit 2.0, or Visual Studio .NET using the Interop facilities provided by the common language runtime. Both methods require the WSDL file that provides a description for the methods exposed by the Web service:

Ee251575.bts_wp_net_04(en-US,BTS.10).gif

Figure 4. The BizTalk Orchestration schedule describes the business process, which is to be implemented

If the Web service was created using the SOAP Toolkit, the WSDL file will have been generated using the SOAP Toolkit WSDL Generator utility. If, on the other hand, the Web service was created using Visual Studio .NET, the characteristics of the Web service can be displayed by browsing to the service's .asmx file. This URL provides a general description of the Web service, details about the format of the SOAP messages required to invoke the various methods, and the WSDL file for the Web service.

For example, if a Web service named BankVBNet is created and deployed on a local computer, the WSDL file for the Web service will be located at:

http://localhost/BankVBNet/BankVBNet.asmx?WSDL

This URL can be used directly by the proxy client to access the WSDL file for the Web service.

The included sample (CreditCheck) is a BizTalk Orchestration that implements a business process that receives a document, decides whether the document is for a purchase or a return, then calls an XML Web service at a bank to credit or debit the customer's account. Several actions in this schedule (Purchase Goods and Return Goods) are implemented using a Web service named BankVBNET, written in Visual Basic .NET. BankVBNET exposes three methods:

CheckCredit(ByRef AccountNo As Integer, _
ByRef AmountToDebit As Integer) As Integer

Credit(ByRef AccountNo As Integer, _
ByRef AmountToCredit As Integer) As Boolean

Debit(ByRef AccountNo As Integer, _
ByRef AmountToDebit As Integer) As Boolean

Each of these methods uses Microsoft ActiveX® Data Objects (ADO) to run a stored procedure on the database to perform the appropriate function. The following code shows the CheckCredit method:

Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebMethod()>Public Function CheckCredit(ByRef AcctNo As Integer, _
ByRef AmountToDebit As Integer) As Integer

        Dim myConn As New ADODB.Connection()
        Dim myCommand As New ADODB.Command()
        Dim myConnectionString As String

        myConnectionString = "……"
        myConn.Open(myConnectionString)

        myCommand.ActiveConnection = myConn
        myCommand.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
        myCommand.CommandText = "CheckCredit"

        myCommand.Parameters.Refresh()
        myCommand.Parameters("@AccountNo").Value = AccountNo
        myCommand.Parameters("@AmountToDebit").Value = AmountToDebit

        myCommand.Execute()

        CheckCredit = CInt(myCommand.Parameters( _
                                "@AccountBalanceIfCredited").Value)

        myCommand = Nothing
        myConn = Nothing
    End Function

Notice the WebMethod attribute at the start of the Visual Basic method, exposing the method as a Web service. This Web service can now be invoked by any client application that sends the appropriate SOAP requests to the Web service at:

http://localhost/BankVBNet/BankVBNet.asmx

Because BizTalk Orchestration Designer cannot call the Web service, a COM object that BizTalk Orchestration Designer can call is created. This COM object acts as a client proxy object for the XML Web service.

Ee251575.bts_wp_net_05(en-US,BTS.10).gif

Figure 5. The COM object serves as a proxy for the Web service

The COM object uses the SOAPClient object from SOAP Toolkit 2.0 to call the Web service. The client proxy object either directly mirrors the methods exposed by the Web service or performs more complex operations by aggregating several of the exposed Web service methods. To implement each of these methods, the client object merely creates the SOAPClient object, loads the WSDL file, and then calls the appropriate method on the Web service. For example, the Purchase method is implemented as:

Public Function Purchase(AccountNo As Integer, _
PurchaseAmount As Integer) As String

    Set SoapClient = CreateObject("MSSOAP.SoapClient")
    SoapClient.mssoapinit _ 
"http://localhost/BankVBNet/BankVBNet.asmx?WSDL", _
    "Account", "AccountSoap" 
    
If SoapClient.CheckCredit(AccountNo, PurchaseAmount) > 0 Then
        If SoapClient.Debit(AccountNo, PurchaseAmount) Then
            Purchase = "Successful purchase"
        Else
            Purchase = "Error while purchasing"
        End If
    Else
        Purchase = "Not enough money to buy this item"
    End If
    Set SoapClient = Nothing
End Function

This particular proxy object creates a more complex business process by combining several methods from the Web service. When this object is compiled, it generates a COM component that is linked into the orchestration.

Implementing an XML Web Service Using Orchestration

A BizTalk Orchestration can be exposed as an XML Web service in three ways:

  • Programmatically
  • Using SOAP Toolkit 2.0
  • Using Visual Studio .NET

Ee251575.bts_wp_net_06(en-US,BTS.10).gif

Figure 6. The COM object exposes the BizTalk Orchestration as an XML Web service

Executing orchestrations programmatically

An XLANG schedule is a process created in the Microsoft Visio-based BizTalk Orchestration Designer, serialized in XML, and executed under the control of COM+ services (called XLANG Scheduler). It is possible to run an entire orchestration as a COM component under the control of COM+ services. The orchestration engine effectively provides a powerful mechanism for business process automation, implemented with COM+ components.

Ee251575.bts_wp_net_07(en-US,BTS.10).gif

Figure 7. The XLANG Scheduler application is one of the COM+ applications

By default, when BizTalk Server is installed, it creates this single COM+ package to run all schedules on that server and adds an XLANG tab to the COM+ Applications Properties dialog box. When a new COM+ application is created, this additional tab can be used to specify that the COM+ application is also a host for XLANG schedule instances.

A client application can invoke these XLANG schedule instances using COM by specifying the path to the .skx (XML file) and the orchestration port, as in the following code example:

set sked = GetObject("sked:///path-to-skx-file/port-name")

Alternatively, the common language runtime Interop Services can be used from within a Visual Studio .NET application to execute a schedule either late bound (shown) or early bound.

The included CreditCheck sample uses several COM objects (CreditChecker and CreditCheckUtil) to implement a simple business process within an orchestration that could be called through an ASP page. The sample shows how this orchestration can be "published" as an XML Web service either by using COM components supplied by SOAP Toolkit 2.0, or by using Visual Studio .NET and the common language runtime.

Ee251575.bts_wp_net_08(en-US,BTS.10).gif

Figure 8. The Orchestration for the CreditCheck sample shown in BizTalk Orchestration Designer

Also, once the Web service has been created, it can be invoked by the client application either using the SOAPClient COM object supplied by SOAP Toolkit 2.0, or using Visual Studio .NET and the common language runtime.

Implementing a Web service using SOAP Toolkit 2.0

To implement an XML Web service using SOAP Toolkit 2.0, a simple COM object is created using Visual Basic 6.0. This COM object instantiates an instance of the schedule by binding to a moniker that represents the schedule. The code binds to a specific port on the schedule (CreditCheck), which is implemented as a COM component method call. The method serves only to pass a supplied value—the number of the account to be credit checked—into the port. The value is passed to successive actions in the schedule (and hence to the ports and implementations linked to those actions) using the data flow on the schedule's Data page.

The code then waits for the result of the schedule by attaching to another port at the end of the schedule, and waiting for the result to be returned from this port (a True or False value determining whether the CreditCheck succeeded or failed), as shown in the following code:

Public Function CheckCredit(AccountNo As Integer) As Boolean
  Dim sskedURL As String
  Dim sked As Object
  
  sskedURL = "sked:///" & App.Path & "\creditcheck.skx/CreditCheck"
  'Start the schedule
  Set sked = GetObject(sskedURL)

  'Start the credit check
  sked.StartCreditCheck (AccountNo)

  'Wait for the results
  CheckCredit = sked.IsCreditApproved()
End Function

This code is compiled to produce a DLL. You can then create the Web service by running the SOAP Toolkit WSDL Generator utility (see Implementing XML Web Services Using SOAP Toolkit 2.0). The COM object provides the implementation for the Web service and acts as a proxy for the orchestration.

Implementing a Web Service using Visual Studio .NET

To implement the same code using Visual Studio .NET and the common language runtime, a Web service project is created. This project implements a class that is derived from System.Web.Services.WebServices. This class exposes one or more class methods as WebMethods, by prefixing the method declaration with a [WebMethod] attribute.

The method itself invokes the schedule using the Marshal.BindToMoniker method from the System.Runtime.InteropServices namespace (see Starting an XLANG Schedule), as shown in the following code:

[WebMethod]
public Object RunSked(string skedMoniker, int accountNo)
{
Type skedType;
Object sked = null;
try 
{
sked = Marshal.BindToMoniker(skedMoniker);
skedType = sked.GetType();

// Set up the parameters
Object[] prms = new Object[1];
prms[0] = accountNo;
skedType.InvokeMember("StartCreditCheck", 
System.Reflection.BindingFlags.InvokeMethod, 
null, sked, prms);
result = skedType.InvokeMember("IsCreditApproved", 
System.Reflection.BindingFlags.InvokeMethod, 
null, sked, null);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine (ex.Message);
throw new Exception(ex.Message, ex);
}
finally
{
Marshal.ReleaseComObject(sked);
}
}

This example shows late binding using reflection. It is also possible to do early binding by generating a .NET assembly corresponding to the type library information in skedcore.dll. The tlbimp tool from the .NET Framework Software Development Kit (SDK) is used to generate a strong named assembly, and then a reference to this assembly is added to the project, as shown in the following code:

using <namespace corresponding to skedcore typelib>;

...

IWFWorkFlowInstance oSked = 
Marshal.BindToMoniker(skedMoniker) as IWFWorkflowInstance;

...

Implementing the Client of the Orchestration Web Service

Invoking a Web service using SOAP Toolkit 2.0

A Web service can be invoked from a client application that has been built using either the SOAPClient object from SOAP Toolkit 2.0, or the common language runtime.

If the SOAPClient COM component is used, the SOAPClient COM object is simply created, then initialized with the WSDL file that describes the Web service. The methods on the SOAPClient object can then be invoked, as shown in the following code:

Dim SoapClient
    
Set SoapClient = CreateObject("MSSOAP.SoapClient")
SoapClient.mssoapinit _
"http://localhost/creditcheck/creditcheck.wsdl"
MsgBox SoapClient.CheckCredit(5555)
Set SoapClient = Nothing

Invoking a Web service using Visual Studio .NET

To access a Web service from a client application that has been built using Visual Studio .NET, a reference to the Web service must be added to the project. Web service discovery is the process of searching for and examining the service descriptions of available XML Web services. The service description details which services are available and how to interact with them. Once a Web service has been discovered, it can be added as a Web reference to the Visual Studio .NET project.

Ee251575.bts_wp_net_09(en-US,BTS.10).gif

Figure 9. The Web References section of the Project Explorer in Visual Studio.NET

To add a Web reference:

  1. On the Project menu of your application, click Add Web Reference.

    The Add Web Reference dialog box appears.

  2. In the Address box, type the URL to the .disco, .vsdisco, .wsdl, or .asmx file of the Web service to access.

Visual Studio .NET will download the service description and generate a proxy class to interface between the application and the Web service. The proxy class is then used in the client application to represent (and invoke) the functionality of the Web service. The following code shows the same Web service being invoked as in the previous topic:

Boolean result;
short accNo = 5555;
localhost.CreditCheck account = new localhost.CreditCheck();

result = account.CheckCredit(ref accNo);

Loosely Coupled Asynchronous XML Web Services and Correlation

XML Web services are a key technology for delivering highly distributed applications. However, building applications in a distributed, loosely coupled environment introduces some challenges.

Most applications today that consume XML Web services invoke such services the same way they would invoke a COM component on another server using DCOM. The calls are synchronous, and the calling application cannot handle situations where the Web service is unavailable or the response from the Web service falls outside acceptable limits. In essence, the SOAP over HTTP call has replaced the RPC call over the network.

This poses some problems for the application architect. When building an application that is distributed across an enterprise, the architect typically has control over the responsiveness and availability of the distributed services used to build the application. However, in the event of XML Web services, which provide services that are distributed across enterprise boundaries, the architect typically has no control over the responsiveness or availability of the services.

Sync on async

Decoupling the Web service invocation from the invocation of the service proxy by the application can summarize possible solutions to these concerns. That is, the application can asynchronously issue a request for service (from a proxy), and application services ensure that the request is eventually submitted to the Web service for processing. Of course, the system must also be able to eventually return a response to the calling application (again, asynchronously). This mechanism is sometimes called "sync on async."

BizTalk Orchestration, a key part of BizTalk Server, applies directly to this problem. BizTalk Orchestration was built to solve the problems associated with managing long-running, loosely coupled business processes that are distributed across organizational boundaries. BizTalk Orchestration provides services, such as transactions (both DTC transactions, and timed and long-running transactions), exception handling, and transaction compensation, to allow the application designer to design robust business processes that are capable of recovering from failure. These are the facilities required to build robust XML Web services.

Web service example: Processing visa applications

Imagine an Immigration Department that has a legacy mainframe application that is capable of processing applications for visas. This application is usually run by Immigration Department staff, which uses a terminal to manually key in application details. The department decides to provide access to this application to immigration consultants, so they can enter applications on behalf of their clients. Because the immigration consultants have their own applications, the Immigration Department provides a Web service interface to the legacy application.

The XML Web service does have associated problems. For one, the mainframe application is periodically unavailable. Also, because all applications are run in a batch every hour, the application is not capable of providing a synchronous response to the request. To resolve these issues, BizTalk Server Orchestration uses a schedule to implement the Web service, as shown in the following illustration.

Ee251575.bts_wp_net_10(en-US,BTS.10).gif

Figure 10. Schematic representation of the visa processing application

To implement this application:

  1. The Web service receives a visa application request (formatted as a SOAP message).
  2. This initiates the schedule that implements the Web service. The schedule submits the visa application to the legacy mainframe application (using BizTalk Server Messaging), where it will be batched until a later time. A unique ID or correlation number is also attached to this submission.
  3. The schedule returns the correlation number to the client application as the response from the Web service.
  4. Eventually, the mainframe application processes the visa application, and generates a response. This response is sent back to the Web service, together with the correlation number for that specific response. The correlation number ensures that the response is linked to the appropriate initiating request.
  5. At some later time, the client application requests the response from the Web service (by calling another method on the Web service and quoting the correlation number).

The XLANG Scheduler Engine provides most of this functionality with no additional coding. The XLANG Scheduler Engine provides the following functionality:

  • Each Web service request is implemented as a separate thread of execution, with automatic invocation of the correct instance of the schedule based on the correlation coefficient.
  • If individual instances of the schedule are running for long periods of time, they will be automatically dehydrated to the database, and then rehydrated when required.
  • BizTalk Orchestration Designer can provide additional error handling in the schedule using transactions, exception handling, and compensation processing.

The result is a Web service that features high-availability and responsiveness, despite the fact that the implementation of the Web service depends on an application service that is neither highly available nor responsive.

For a further example of these types of Web services, go to the Microsoft Download Center Web site, which illustrates highly scalable business processes using BizTalk Orchestration, fed by asynchronous XML Web services and correlation.

BizTalk Messaging and XML Web Services

Converting Legacy Protocols to Web Service Requests

Imagine a legacy application that uses a custom protocol to invoke a service. For example, many banks provide credit card authentication and transaction processing using a protocol known as ISO 8583. This protocol consists of delimited requests and responses transmitted between a client and the bank server, transmitted over a network pipe.

The client sends the sequence to request a credit card purchase, for example:

"P" ~ Merchant ID ~ Sequence Number ~ ~ Amount ~ Card No ~ Expiry Date

Other messages are also provided by the protocol to authorize a transaction or request a refund.

The bank then builds a service to provide credit card processing capabilities to merchants, using Visual Studio .NET. The service is delivered as a Web service, so it is easily accessible by e-commerce Web applications, and uses SOAP as the message protocol (which Visual Studio .NET supports natively). However, because the bank still needs to support older applications that use the ISO 8583 protocol, the service must also be able to receive requests and send responses in this format.

The functionality to process the older ISO 8583 format could be provided by writing custom parser code that processes the ISO 8583 message and then calls the Web service. However, writing such string parsing code is tedious. Instead, you can use BizTalk Server Messaging to receive and parse the ISO 8583 message, convert it to XML, and then pass the message on to an application integration component (AIC), which calls the Web service.

The AIC can be built using Visual Studio .NET "" and can call the Web service by adding a Web reference to the Web service when building the AIC (see Invoking a Web service using Visual Studio .NET).

Extending BizTalk Server with .NET

.NET Application Integration Components

The most obvious way to extend BizTalk Server with .NET is to develop extensions to BizTalk Server using Visual Studio .NET. BizTalk Server provides an application integration framework that is simple, but extensible and flexible. This framework takes the form of application integration components (AICs), two types of which are supported by BizTalk Server: AICs supporting the BTSAppIntegration interface and pipeline component AICs.

AICs supporting the BTSAppIntegration interface

AIC components that support the BTSAppIntegration interface provide a lightweight model for application integration, one that does not support design-time user interface or configuration properties. This model requires a single interface that contains a single method as an entry point.

Pipeline component AICs

Pipeline component AICs support the same interfaces as Microsoft Commerce Server 2000 pipeline components. They were originally derived from the Microsoft Site Server 3.0 Commerce Edition Order Processing pipeline (OPP) and Commerce Interchange pipeline (CIP) components. BizTalk Server 2000 itself was derived from the CIP and the Commerce Interchange Pipeline Manager (a free add-on to Site Server 3.0 Commerce Edition, available from Microsoft). Because BizTalk Server supports these Commerce Server 2000 pipeline components, integration components written for the CIP and OPP are compatible. In fact, BizTalk Server and Commerce Server 2000 share the same Microsoft Commerce Pipeline Components Type Library (Pipecomplib.tlb).

Pipeline components must support the IPipelineComponentAdmin, as well as the more complex IPipelineComponent interfaces. In return, these components provide a user interface where configuration properties can be specified and have access to additional information during run time.

Building a BTSAppIntegration AIC with .NET

To build a BTSAppIntegration AIC with the .NET Framework, common language runtime, and Visual Studio .NET integrated development environment (IDE), the standard development approach must be modified. Previously, Microsoft Visual Basic or Visual C++ was used to build a COM component that implemented the IBTSAppIntegration interface. This interface has a single method:

ProcessMessage(ByVal bstrDocument As String) As String

.NET assembly

With Visual Studio .NET, instead of a simple COM+ component implementing a COM interface, a .NET assembly that interoperates with COM through the common language runtime is created. The common language runtime can call COM objects as if they were managed objects, and managed components can be exposed as if they were COM objects. The runtime handles marshalling data between the managed environment and the unmanaged COM component. This functionality is provided by the ServicedComponent interface in the common language runtime.

A serviced component is a class authored in a Common Language Specification (CLS)-compliant language that implements the System.EnterpriseServices.ServicedComponent interface. That is, the class is derived from this interface either directly or indirectly. A class configured this way is hosted as a COM+ application and can use the COM+ services. In addition, this class will implement the IBTSAppIntegration interface.

.NET runtime callable wrapper

The BTSAppIntegration AIC is built using the standard COM+ Interop facilities supplied by the .NET Framework. Before a COM+ interface can be implemented, or an existing COM+ component can be instantiated, a .NET runtime callable wrapper (RCW) needs to be created for the COM+ interface. In the included sample, a RCW for the BizTalk Server Application Integration Component Type Library is created. Because the RCW will be used within another strong name assembly, it must also have a strong name key when it is created.

The RCW can be easily created within the Visual Studio .NET IDE by adding a reference to the BTSCompLib.tlb in the project, and automatically generating a Primary Interop Assembly Wrapper. To do this, right-click the References section of the project and select Add Reference from the context menu. A dialog box lists all registered COM types. Select Microsoft BizTalk Server Interchange 1.0 Type Library. This is analogous to adding specific COM+ references to a Visual Basic 6.0 program.

Notes

  • If the Visual Studio .NET IDE generates the RCW for the COM Type Library automatically, a strong name key file for the assembly must be added before adding any COM+ references. Otherwise, the COM wrapper generated by the Visual Studio .NET IDE will not be strongly typed, thus preventing the .NET DLL from being hosted by COM+.
  • Visual Studio .NET uses the Output Path directory (bin\debug, by default) of the project to look for a strong name key file when generating a Primary Interop Assembly Wrapper for referenced components. If the IDE is used to generate the wrapper, the strong name key file must be in this directory and a reference to it must be in the Project Properties dialog box.

The RCW for the BTSCompLib.tlb can also be created using the command line, which has the advantage that the RCW is created once, and can then be used across multiple projects. To enable the RCW to be accessed by multiple projects, it is placed in the Global Assembly Cache (GAC).

To create the .NET integration component:

  1. To sign the wrapper assembly with a strong name, a cryptographic key pair must be supplied, so first create a strong name file. The key pair is created using the Strong Name tool (Sn.exe). Key pair files usually have an .snk file extension, as shown in the following code:
    cd C:\Program Files\Microsoft.NET\Primary Interop Assemblies
    sn -k BTSAppIntegration.snk
    
    
  2. Create a RCW, which is signed with the strong name key file created in step 1, to create a strong name assembly, as shown in the following code:
    tlbimp "c:\Program Files\Microsoft BizTalk
    Server\btscomplib.tlb" /out: BTSAppIntegration.dll /namespace: 
    BTSAppIntegration /asmversion:1.0 /keyfile: 
    BTSAppIntegration.snk /primary
    
    
  3. Place the assembly in the GAC, as shown in the following code:
    gacutil.exe /i BTSAppIntegrationLib.dll
    
    
  4. Create a new Microsoft Visual C# Project – Class Library. Delete Class1, which was created when the project was created.
  5. In Visual Studio .NET, right-click the References section of the project and select Add Reference from the context menu. Because the RCW was placed into the GAC, it will appear in the Add References dialog box.
  6. Create another strong name key file and add it to the project, as shown in the following code:
    cd path_to_project
    sn -k BizTalkAIC.snk
    
    
  7. Create the class that implements the IBTSAppIntegration interface. This class should be sub-classed from both the ServicedComponent .NET class and the IBTSAppIntegration interface. Attach a GUID attribute to the class, so the same GUID will be used for each compilation (similar to setting Binary Compatibility in a Visual Basic 6.0 DLL project), as shown in the following code:
    [Guid("1AA73916-FB97-4049-B1AF-DF6BBB43CDB2")]
    // BTSInterop Inherits ServicedComponent and IBTSAppIntegration
    public class AICtoFile: ServicedComponent, IBTSAppIntegration
    {
    public AICtoFile()
    {
    }
    
    string ProcessMessage(string strDocument)
    {
    // Write the Input XML to a file
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(strDocument);
    xmlDoc.SelectSingleNode("BTSAICRoot/MessageText").InnerText
    = "Message from AIC";
    xmlDoc.Save(@"C:\Samples\BTSAIC.NET\Reply\Output.XML");
    
    // Simply return the Input as Output
    return strDocument;
    }
    }
    
    
  8. Edit AssemblyInfo.cs, and add references for the System.EnterpriseServices package and the generated strong name key file. Also, set the attributes for the COM+ package that will be created to host the COM+ Interop component, as shown in the following code:
    // Add a reference to the EnterpriseServices package
    using System.EnterpriseServices;
    
    // Insert reference to Strong Name Key
    [assembly: AssemblyKeyFile("../../BizTalkAIC.snk")]
    
    // Add the COM+ Application configuration
    [assembly: ApplicationName("CSharpBTSAIC")]
    [assembly: ApplicationID("B6A17F8D-9CFC-433c-B907-687D539AA892")]
    [assembly: Description("BTS AIC Using C#")]
    [assembly: ApplicationActivation(ActivationOption.Server)]
    
    
  9. Build the project and register the assembly with COM+, as shown in the following code:
    cd path_to_project/bin/Debug
    regsvcs project_name.dll
    
    
Note   If a class in the .NET Framework uses COM+ services, it must be registered in a COM+ application as a regular COM component. When an instance of the class is created within .NET, registration is automatic, based on the attributes in the assembly. However, if a new instance of the class is required from an unmanaged (COM) environment, the assembly must be registered manually. You can register the assembly by using the tool regsvcs.

Debugging the .NET AIC

Writing numerous trace statements in code is an unsatisfactory way to debug AIC code. And with the power and sophistication of the Visual Studio .NET IDE, there is a better way.

BizTalk Server runs as a Microsoft Windows® 2000 service. When the AIC is invoked, it runs under the control of the COM+ services, by default as a separate process. This means any bugs in the AIC will not cause BizTalk Server to fail.

Because the AIC is deployed as a DLL rather than an executable, COM+ provides an application, called dllhost.exe, in which the AIC can run. Looking at the processes running on a server using Task Manager typically reveals one or more dllhost.exe processes running. These are COM+ components running as applications under COM+.

To debug AICs, you could attach the Visual Studio .NET IDE to the appropriate dllhost.exe process, but it is not immediately obvious which process is the one supporting the specific COM+ component (AIC) to be debugged. Instead of running the AIC as a separate process, however, it can be run temporarily within the same process as the BizTalk Server service, allowing the Visual Studio .NET IDE to be attached to this process. To do this, the BizTalk Server service is stopped, and invoked directly from the Visual Studio .NET IDE.

To debug a custom BizTalk Server component:

  1. On the Start menu, point to Settings, click Control Panel, double-click Administrative Tools, and then double-click Component Services.

    The COM+ applications on the system are displayed.

  2. Select the AIC COM+ application (CSharpBTSAIC) and click Shut Down.
  3. Set the COM+ application to run as a library package.
  4. In the Component Services console, stop the BizTalk Messaging Service.
  5. Load the BizTalk Server AIC project into Visual Studio .NET.
  6. Set the debugging properties for the BizTalk Server AIC project so that Visual Studio .NET will start the BizTalk Server executable (causing it to run as a normal application, not as a Windows service). Right-click the BizTalk Server AIC project in Solution Explorer and click Properties.
  7. In the left-hand pane, click Configuration Properties, then click Debugging, and set Debug Mode to Program.
  8. Set Start Application to the path where BizTalk Server is installed (typically, \Program Files\Microsoft BizTalk Server\MSCIS.exe). This is the executable for the BizTalk Messaging Service. Click OK.
  9. Set a breakpoint at an appropriate place in the code and, on the Debug menu, point to Debug and click Start, to start BizTalk Server from the Visual Studio .NET IDE.
  10. Call the code in the AIC by dropping a file into the file drop directory.

    The File Listener will submit the file to BizTalk Server, which will call the AIC. Visual Studio .NET will stop execution of the AIC at the breakpoint that was set in step 9. You can now use all of the debugging features of Visual Studio .NET IDE to debug the component, as shown in the following illustration.

    Click here to see larger image

    Figure 11. Debugging a BizTalk Server component in Visual Studio .NET (click image to see larger picture)

After debugging, don't forget to reset the COM+ application to run as a Server application, and to restart the BizTalk Server service.

Building a Custom Preprocessor in BizTalk Server Using .NET

A custom preprocessor can be implemented in BizTalk Server in a similar manner to the AIC. Rather than implementing the IBTSAppIntegration interface, the customer preprocessor must implement the IBTSCustomProcess interface.

To build a custom preprocessor using C#:

  1. Create the RCW with the Visual Studio .NET command prompt, sign this assembly with a strong name, and place the assembly in the GAC, as shown in the following code:
    cd C:\Program Files\Microsoft.NET\Primary Interop Assemblies
    
    sn -k BTSAppIntegration.snk
    
    tlbimp "c:\Program Files\Microsoft BizTalk
    Server\btscomplib.tlb" /out: BTSAppIntegration.dll /namespace: 
    BTSAppIntegration /asmversion:1.0 /keyfile: 
    BTSAppIntegration.snk /primary
    
    gacutil.exe /i BTSAppIntegrationLib.dll
    
    
  2. Create a new Visual C# Project – Class Library, and add references to BTSCompLib and System.EnterpriseServices from the list of .NET references.
  3. Create another strong name key file, and add this to the project.Delete class that was generated when the project was created.
  4. Create a new class that implements the IBTSCustomProcess interface. This class should be sub-classed from both the ServicedComponent .NET class and the IBTSCustomProcess interface. Attach a GUID attribute to the class.
  5. Edit AssemblyInfo.cs, and add references for the System.EnterpriseServices package and the generated strong name key file.
  6. Set the attributes for the COM+ package that will be created to host the COM+ Interop component.
  7. Build the project and register the assembly with COM+, as shown in the following code:
    cd path_to_project/bin/Debug
    regsvcs project_name.dll
    
    

Step 5 automatically creates a COM+ application package, which is given the name specified in the AssemblyInfo.cs file.

However, unlike the AIC, the custom preprocessor is still not available to BizTalk Server. For example, it will not show up in the preprocessor drop-down list when you create a File receive function. To make the preprocessor available, more information must be added to the registry so that BizTalk Server can recognize (or discover) the custom preprocessor. This information consists of a COM category ID, which indicates that the component created implements a specific category (IBTSCustomProcess). A simple registry file (.reg) can be used to add the category ID.

Other BizTalk Server Development with the .NET Framework

Starting an XLANG Schedule

To start an XLANG schedule using COM+, the GetObject method is used. This accesses a Microsoft ActiveX object from a file and assigns the object to an object variable. The parameter to GetObject is a moniker that can either create a new schedule instance or refer to an existing instance. Applications can create new schedule instances by creating a moniker of the form:

set sked = GetObject("sked:///path-to-skx-file/port-name")

From this, you get a COM reference that lets you communicate with the specific port on the new schedule instance.

The scheduler engine has another form of moniker that allows a port on a specific, existing schedule instance. The engine will create these fully qualified port names if a dataflow is established from the "Port References" message to another outgoing message. The common scenario for this is when a specific schedule instance is rehydrated later (possibly months later), when a message arrives.

To start an XLANG schedule using the common language runtime, the .NET equivalent of GetObject, Marshal.BindToMoniker is used. This method is found in the System.Runtime.InteropServices namespace. The following code sample is a small function you can use to start a schedule:

using System.Runtime.InteropServices;

static void LaunchXLANGSchedule(string skedMoniker)
{
Object sked = null;
try 
{
sked = Marshal.BindToMoniker(skedMoniker);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine (e.Message);
throw new Exception(e.Message, e);
}
finally
{
Marshal.ReleaseComObject(sked);
}
}

Note   The instantiation of the schedule is asynchronous (the BindToMoniker method returns immediately).

Passing data to an XLANG schedule

The following code sample illustrates how to start an XLANG schedule and pass data to a port named InputPort, which is a COM binding port. The InvokeMember call will create the COM component and call the member function bound to this port. The specified parameters will be passed in as parameters to this method call. The result of the method call will be returned as the result of the InvokeMember call.

Note   This COM binding port can also be set for "No Instantiation," since it can be used just to pass the value (1 in this case) into the schedule.
using System.Runtime.InteropServices;
using System.Reflection;

public void LaunchXLANGSchedule() 
{
Object sked = null;
Type typ;

try {
string skedMoniker = @"sked:///C:\Sched.skx/InputPort";
sked = Marshal.BindToMoniker(skedMoniker);
typ = sked.GetType();

// Set up parameters
Object[] prms = new Object[1];
prms[0] = 1;
typ.InvokeMember("Submit", BindingFlags.InvokeMethod, 
null, sked, prms);
}

catch (Exception e)
{
System.Diagnostics.Debug.WriteLine (e.Message);
throw new Exception(e.Message, e);
}
finally
{
Marshal.ReleaseComObject(sked);
}
}

The application binds to individual ports by calling the InvokeMember method to connect to specifically named ports. Values are passed into these ports using a parameter array, and received from these ports by the return value of the call.

Submitting Documents to BizTalk Server from the .NET Framework

When building applications using Visual Studio .NET, there are two common mechanisms to submit documents to BizTalk Server from these applications:

  • Directly submitting using the IInterchange interface
  • Submitting by writing the document to a Message Queuing message for BizTalk Server to pick up using a Message Queuing receive function
    Note   The second method, while appearing to be more indirect, actually performs quite well, and also increases the fault tolerance of the application, particularly when the application is deployed across multiple servers.

Submitting documents using the IInterchange interface

Submitting a document to BizTalk Server using the IInterchange interface also leverages off the functionality supplied by the COM Interop facilities in .NET. Once again, a .NET Primary Interop Assembly Wrapper for the COM+ IInterchange interface needs to be created before using it.

You can create the wrapper either by adding a reference to the Visual Studio project (right-click the References section of the project and add the Microsoft BizTalk Server Interchange 1.0 Type Library), or by creating the .NET Primary Interop Assembly Wrapper once and sharing this across projects by placing it in the GAC, as shown in the following code:

REM Create a strong name
sn -k BTSInterchange.snk
REM Create a runtime-callable wrapper
tlbimp "c:\Program Files\Microsoft BizTalk Server\cisapi.tlb" /out: 
   BTSInterchangeLib.dll /namespace: BTSInterchangeLib /asmversion:1.0 
      /keyfile: BTSInterchange.snk 
REM Place the assembly in the Global Assembly Cache
gacutil.exe /i BTSInterchangeLib.dll

For more information about creating the Primary Interop Assembly Wrapper, see the .NET runtime callable wrapper area of Building a BTSAppIntegration AIC with .NET.

The following code shows how the wrapper object for the IInterchange interface is created, invoked, and released using C#:

using System.Runtime.InteropServices;
using System.IO;

public string SubmitToBizTalk(string document)
{
string messageid;
BTSInterchangeLib.Interchange interchange = null;
try {
interchange = new BTSInterchangeLib.Interchange();
messageid = interchange.Submit(0, document, "", "", "", 
"", "", "Channel Name", "", "", 0); 
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine (e.Message);
throw new Exception(e.Message, e);
}
finally
{
Marshal.ReleaseComObject(interchange);
}
return messageid;
}

The call to Marshal.ReleaseComObject will call the Release method on the COM object, and if the reference count of the COM object reaches zero, the COM object will free itself. Note that the .NET Primary Interop Assembly Wrapper is not reclaimed until it is eventually garbage-collected. This method is used to explicitly control the lifetime of a COM object.

Submitting documents using Message Queuing

Submitting documents to BizTalk Server by posting them to a message queue, and then receiving them using a BizTalk Server receive function, is an efficient mechanism for submitting documents to BizTalk Server, as well as adding useful failover attributes to the application.

The common language runtime provides a mechanism to write messages to Message Queuing. This is found in the System.Messaging namespace and consists of a number of classes, including the MessageQueue class. It is also necessary to use the ActiveXMessageFormatter class to serialize (and de-serialize) the message into (and from) Message Queuing messages using a binary format.

The following code sample shows how a message is sent to Message Queuing that is suitable for a BizTalk Server receive function:

void SendToMSMQ(string queueName, string body, string label)
{
MessageQueue queue = new MessageQueue();

if (MessageQueue.Exists(queueName))
{
//Set Queue Path
queue.Path = queueName;
Message msg = new Message();

// Assumes the dest queue already exists
ActiveXMessageFormatter format = new 
                        ActiveXMessageFormatter();
format.Write(msg, body);
if (queue.Transactional) 
{
MessageQueueTransaction trans1 = new
                         MessageQueueTransaction();
trans1.Begin();
queue.Send(msg, label, trans1);
trans1.Commit();
}
else
queue.Send(msg, label);
}
}

Note   The code tests to see if the queue is transactional. For transactional message queues (and most message queues used with BizTalk Server queues are transactional), the call to Send must also specify a transaction (which is committed) in order for the call to succeed. BizTalk Server 2000 Service Pack 1a (SP1a) or later is required for this code.

Acknowledgements

This paper summarizes the work of many people. In particular, Michael Royster, Matt Fangman, Scott Woodgate, Emil Velinov, Grant Bolitho, Ken Circeo, and Renee Wesberry provided invaluable comments, code snippets, and reviews of this document.

Show:
© 2014 Microsoft