Geeks With Blogs

News
Paul's Petrov Whiteboard [BizTalk, Enterprise Application Integration, Business Process Automation, SOA, .NET]

In service-oriented solution I designed there was an interface where some operations were handled by BizTalk while some were just straight data services with no need for orchestration. The idea was to keep web service operations in one endpoint for business reasons, security and operational considerations. Using WCF way of describing interface example may look like this:

[ServiceContract(Name="TestService", Namespace = "http://mynamespaces.com/TestService")]
public interface ITestService

{
  [OperationContract(Name =
"ProcessItem",
    Action=“http://mynamespaces.com/TestService/ProcessItem“,
    ReplyAction="http://mynamespaces.com/TestService/ProcessItemResponse"
)] 
  ProcessItemResponse ProcessItem(DataItem item);

  [OperationContract(Name=
"GetDataItem",
    Action=http://mynamespaces.com/TestService/GetDataItem,
    ReplyAction="http://mynamespaces.com/TestService/GetDataItemResponse"
)]
  DataItem GetDataItem(DataItemInfo info);
}

ProcessItem operation is BizTalk orchestration exposed as web service and GetDataItem is a simple data service that does not require orchestration. The question is how to generate WSDL contract and server proxy knowing that BizTalk publishing process will override any changes we make to the proxy code. It is quite possible since BizTalk proxy derives from System.Web.Services.WebService class and is defined in partial class. All we need is to put BizTalk operations in one code file and the rest into another and provide proper binding declarations on them. Here's code for BizTalk part of the TestService.cs:

    [System.Web.Services.WebServiceBindingAttribute(
        Name
="TestService",
        ConformsTo
= System.Web.Services.WsiProfiles.None,
        EmitConformanceClaims
= false)]
    [System.Web.Services.WebServiceAttribute(
        Name
="TestService",
        Namespace
="http://mynamespaces.com/TestService",
        Description
=null)]
    [System.Web.Services.Protocols.SoapDocumentServiceAttribute(
        Use
=System.Web.Services.Description.SoapBindingUse.Literal, 
ParameterStyle
=
System.Web.Services.Protocols.SoapParameterStyle.Default)]
   
public sealed partial class TestService : Microsoft.BizTalk.WebServices.ServerProxy.ServerProxy
    {

        [System.Web.Services.WebMethodAttribute()]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
           
"http://mynamespaces.com/TestService/ProcessItem",
            OneWay
= false, Use = System.Web.Services.Description.SoapBindingUse.Literal,
            ParameterStyle
=
System.Web.Services.Protocols.SoapParameterStyle.Default,
            Binding
= "TestService")]
        [
return: System.Xml.Serialization.XmlElementAttribute(Namespace="http://mynamespaces.com/TestService",
            ElementName
="ProcessItemResponse")]
       
public TestService.XsdTypes.ProcessItemResponse ProcessItem(
            [System.Xml.Serialization.XmlElementAttribute(Namespace="http://mynamespaces.com/TestService"
,
                ElementName
="ProcessItem")] TestService.XsdTypes.ProcessItem part)
        { //- implementation goes here 
}
    }

What important to note here is the binding declaration using WebServiceBindingAttribute. The same binding name will be used in all operations that implement this interface. This is done using SoapDocumentMethodAttribute with parameter Binding=”TestService”. My binding name usually associated with the orchestration logical port so I have consistent and logical naming. For example, ProcessItemOrchestration will have TestServicePortType (interface, corresponds to WSDL portType) and TestServicePort (implementation). At deployment I simply bind TestServicePort to TestService.asmx receive location. So here goes non BizTalk part of the proxy class TestService.NonBizTalk.cs:

    public sealed partial class TestService
    {

        [System.Web.Services.WebMethodAttribute()]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
           
"http://mynamespaces.com/TestService/GetDataItem",
            OneWay
= false, Use = System.Web.Services.Description.SoapBindingUse.Literal,
            ParameterStyle
= System.Web.Services.Protocols.SoapParameterStyle.Default,
            Binding
= "TestService")]
        [
return: System.Xml.Serialization.XmlElementAttribute(Namespace="http://mynamespaces.com/TestService",
            ElementName
="DataItem")]
       
public TestService.XsdTypes.DataItem GetDataItem(
            [System.Xml.Serialization.XmlElementAttribute(Namespace="http://mynamespaces.com/TestService"
,
                ElementName
="DataItemInfo")] TestService.XsdTypes.DataItemInfo part)
        { //- implementation goes here 
}
    }

Now we're ready to consume this service at one endpoint http://hostname/TestService.asmx and run BizTalk Web Services publishing wizard without worrying to break it every time.

Posted on Monday, August 28, 2006 8:30 PM BizTalk | Back to top


Comments on this post: Inside BizTalk Web Service Proxy - Operation Binding

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Paul Petrov | Powered by: GeeksWithBlogs.net