65.9K
CodeProject 正在变化。 阅读更多。
Home

BizTalk Server WCF 自定义服务行为

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2012年9月20日

CPOL

1分钟阅读

viewsIcon

31496

BizTalk WCF 自定义服务行为,用于在端口级别发送响应(根据输入填充一些值)。

引言

BizTalk 的 WCF 具有强大的功能。 我们可以做很多事情,只需要去发现它们。 由于它还不是很老,很多内容在网上找不到。 但请相信,它远不止我们想象的那么简单。

我只是与您分享其中一项功能。

背景

问题描述:假设您想创建一个 BizTalk 接收位置(WCF Webservice),并且在接收到此端口上的请求后,需要同步发送一个响应(在同一时间内),响应的 XML 类型为某种类型,但需要从**输入消息字段填充响应 XML 字段**。

注意:在不使用 Orchestration 的情况下解决上述问题。

解决方案

我们可以通过创建一个 WCF-自定义服务行为来解决上述问题,而无需使用 Orchestration。

步骤

  1. 创建一个 BizTalk Server 接收位置,类型为 WCF-CusomIsolated(或者我们可以使用 WCF-Custom,在这种情况下将其托管在 In-Process 宿主中)。
  2. 添加一个类库项目,并添加三个类。
    1. CustomTechKundanBTSResponseProviderBehaviorExtensionElement.cs
    2. //Start CustomTechKundanBTSResponseProviderBehaviorExtensionElement.cs
      using System;
      using System.Collections.Generic;using System.Text;
      using System.ServiceModel.Configuration;
      using System.Configuration;
      using System.Xml.Schema;
      using System.Xml;
      
      namespace Kundan.Integrations.WCF{
        public class CustomTechKundanBTSResponseProviderBehaviorExtensionElement : 
           BehaviorExtensionElement{public CustomTechKundanBTSResponseProviderBehaviorExtensionElement(){
        }
      
        public override Type BehaviorType{
          get{return typeof(CustomTechKundanBTSResponseProviderServiceBehavior);}
        }
      
        protected override object CreateBehavior(){
          return new CustomTechKundanBTSResponseProviderServiceBehavior(SuccesResponse, 
                     ErrorResponse, MaxLengthFaultMessage);}
          [ConfigurationProperty("SuccesResponse", DefaultValue = "", IsRequired = false)]
          public string SuccesResponse{
            get { return (string)base["SuccesResponse"]; }
            set { base["SuccesResponse"] = value; }}
            [
              ConfigurationProperty("ErrorResponse", DefaultValue = "", IsRequired = false)]
            public string ErrorResponse{
            get { return (string)base["ErrorResponse"]; }
            set { base["ErrorResponse"] = value; }}
            [
              ConfigurationProperty("MaxLengthFaultMessage", DefaultValue = "", IsRequired = false)]
            public int? MaxLengthFaultMessage{
              get { return (int?)base["MaxLengthFaultMessage"]; }
              set { base["MaxLengthFaultMessage"] = value; }}
            }
         }
      //End: CustomTechKundanBTSResponseProviderBehaviorExtensionElement.cs
    3. CustomTechKundanBTSResponseProviderMessageInspector.cs
    4. using System;
      using System.Collections.Generic;
      using System.Text;
      using System.ServiceModel;
      using System.ServiceModel.Channels;
      using System.ServiceModel.Dispatcher;
      using System.Xml;
      using System.Xml.XPath;
      
      namespace Kundan.Integrations.WCF{
      
      public class CustomTechKundanBTSResponseProviderMessageInspector : 
          IDispatchMessageInspector{String _succesResponse = null;
      String _errorResponse = null;
      int? _maxLengthFaultString;
      bool _emptyMessage;
      XPathDocument Requestdocument = null;
      XmlDocument xmldoc = null;
      
      public CustomTechKundanBTSResponseProviderMessageInspector(
        String succesResponse, String errorResponse, int? maxLengthFaultString){
      _succesResponse = succesResponse;
      _errorResponse = errorResponse;
      _maxLengthFaultString = maxLengthFaultString;
      }
      #region IDispatchMessageInspector Members
      object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, 
        IClientChannel channel, InstanceContext instanceContext){
      _emptyMessage = request.IsEmpty;
      
      xmldoc = 
      new XmlDocument();xmldoc.Load(request.GetReaderAtBodyContents());
      System.Diagnostics.
      EventLog.WriteEntry("KundanBTS WCF compo", xmldoc.InnerXml);
      
      Message message = Message.CreateMessage(request.Version, null, new XmlNodeReader(xmldoc));
      //copy back the original headers and properties to the
      //new messagemessage.Headers.CopyHeadersFrom(request.Headers);
      message.Properties.CopyProperties(request.Properties);
      //assign the new message to the referenced request messagerequest = message;return null;}
      
      void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState){
      System.IO.
      StringReader stringreader = null;System.Diagnostics.
      EventLog.WriteEntry("KundanBTS WCF compo", "Inside Reply");
      String sErrorResponse = "";
      String sSuccesResponse = "";
      if (!_emptyMessage){
      
      if (reply.IsFault){
      System.Diagnostics.
      EventLog.WriteEntry("KundanBTS WCF compo", "Inside Error");
      //create the error message if the property is setif (
      //        _errorResponse != null && _errorResponse.Length > 0){
      
      if (_errorResponse.Contains("%providerID%")){
      
      string strProvider = null;
      string strRequester = null;
      XPathNavigator navigator = xmldoc.CreateNavigator();
      XPathNodeIterator Providernode = navigator.Select("//*[local-name()='providerID']");
      XPathNodeIterator Requesternode = navigator.Select("//*[local-name()='RequesterD']");
      while (Providernode.MoveNext()){
      strProvider = Providernode.Current.Value;
      }
      
      while (Requesternode.MoveNext()){
      strRequester = 
      "KundanBTS_" + Requesternode.Current.Value;}
      sErrorResponse = _errorResponse;
      sErrorResponse = sErrorResponse.Replace(
      "%providerID%", strProvider);sErrorResponse = sErrorResponse.Replace(
      "%RequesterID%", strRequester);
      stringreader = 
      new System.IO.StringReader(sErrorResponse);
      }
      
      else{return;}
      }
      }
      
      else{
      //create the succes message if the property is
      //setSystem.Diagnostics.EventLog.WriteEntry("KundanBTS WCF compo", "Inside Success");
      string strProvider = null;
      string strRequester = null;
      XPathNavigator navigator = xmldoc.CreateNavigator();
      XPathNodeIterator Providernode = navigator.Select("//*[local-name()='providerID']");
      XPathNodeIterator Requesternode = navigator.Select("//*[local-name()='RequesterID']");
      while (Providernode.MoveNext()){
      strProvider = Providernode.Current.Value;
      }
      
      while (Requesternode.MoveNext()){
      strRequester = Requesternode.Current.Value;
      }
      sSuccesResponse = _succesResponse;
      
      sSuccesResponse = sSuccesResponse.Replace(
      "%providerID%", strProvider);sSuccesResponse = sSuccesResponse.Replace(
      "%RequesterID%", strRequester);stringreader = 
      new System.IO.StringReader(sSuccesResponse);
      
      
      }
      
      XmlTextReader xmlreader = new XmlTextReader(stringreader);
      
      // Create new message Message newMsg = Message.CreateMessage(reply.Version, null, xmlreader);
      // Close the original message and return new messagereply.Close();
      reply = newMsg;
      }
      }#endregion}
      }
    5. CustomTechKundanBTSResponseProviderServiceBehavior.cs
    6. using System;
      using System.Collections.Generic;
      using System.Text;
      using System.ServiceModel.Description;
      using System.Xml.Schema;
      using System.ServiceModel;
      using System.ServiceModel.Dispatcher;
      using System.ServiceModel.Channels;
      namespace Kundan.Integrations.WCF{
      
      public class CustomTechKundanBTSResponseProviderServiceBehavior : 
             IServiceBehavior{String _succesResponse = null;
      String _errorResponse = null;
      int? _maxLengthFaultString;
      public CustomTechKundanBTSResponseProviderServiceBehavior(String succesResponse, 
         String errorResponse, int? maxLengthFaultString){
      _succesResponse = succesResponse;
      _errorResponse = errorResponse;
      _maxLengthFaultString = maxLengthFaultString;
      }
      
      public void AddBindingParameters(ServiceDescription serviceDescription, 
         ServiceHostBase serviceHostBase, 
         System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, 
         BindingParameterCollection bindingParameters){
      }
      
      public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
                  ServiceHostBase serviceHostBase){
      
      CustomTechKundanBTSResponseProviderMessageInspector inspector = null;
      foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers){
      
      foreach (EndpointDispatcher epDisp in chDisp.Endpoints){
      inspector = 
      new CustomTechKundanBTSResponseProviderMessageInspector(_succesResponse, 
          _errorResponse, _maxLengthFaultString);epDisp.DispatchRuntime.MessageInspectors.Add(inspector);
      }
      }
      }
      
      public void Validate(ServiceDescription serviseDescription, ServiceHostBase serviceHostBase){
      }
      }
      }
  3. 编译并 GAC 部署 DLL。
  4. 在 32 位和 64 位 machine.config 文件中,都添加以下行到 2.0 和 4.0 machine.config 文件中。
  5. <add name="CustomTechKundanBTSResponse" 
      type="Kundan.Integrations.WCF.CustomTechKundanBTSResponseProviderBehaviorExtensionElement, 
            Kundan.Integrations.WCF.CustomTechKundanBTSResponse, 
            Version=1.0.0.0, Culture=neutral, PublicKeyToken=c1a801be9a87ef72" />

    重新启动 IIS 和 BizTalk 宿主实例。

  6. 转到 WCF-Custom(或 WCF-CustomIsolated)接收位置,在“行为”选项卡上,右键单击并添加扩展。 您可以在列表中看到 CustomTechKundanBTSResponse,添加它,并提供成功和错误响应 XML。

现在使用您的应用程序或 SOAPUI 进行测试。

© . All rights reserved.