2012-05-04 50 views
13

在我的WCF服務中,我想編輯IClientMessageInspector的BeforeSendRequest和AfterReceiveReply中的SOAP。使用IClientMessageInspector編輯WCF服務的SOAP

我創建了一個自定義的行爲是這樣的:

public class MyBehavior : BehaviorExtensionElement, IEndpointBehavior 
{ 
} 
在類MyBehavior

,我實現IEndpointBehavior方法,如下面的代碼:

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
{ 
    MyInspector inspector = new MyInspector(); 
    clientRuntime.MessageInspectors.Add(inspector); 
} 

MyInspector只不過是從繼承的類IClientMessageInspector。

現在,我的問題是:IEndpointBehavior的ApplyClientBehavior沒有被解僱。但在WCF客戶端,當我加入這個項目的引用,其MyBehavior類存在,並在客戶端下面的代碼寫:

c.Endpoint.Behaviors.Add(new MyBehavior()); 

它工作正常。我的意思是申請客戶端行爲方法被解僱。

我不想問我的客戶手動添加此行爲,我希望這種情況自動發生。我怎樣才能做到這一點?

下面是完整的代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Xml; 
using System.ServiceModel.Configuration; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 
using System.ServiceModel.Channels; 
using System.IO; 

namespace MethodChangeService 
{ 
    public class MyInspector : IClientMessageInspector 
    { 
     public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) 
     { 
      XmlDocument doc = new XmlDocument(); 
      MemoryStream ms = new MemoryStream(); 
      XmlWriter writer = XmlWriter.Create(ms); 
      reply.WriteMessage(writer); 
      writer.Flush(); 
      ms.Position = 0; 
      doc.Load(ms); 
      ChangeMessage(doc, false); 
      ms.SetLength(0); 
      writer = XmlWriter.Create(ms); 
      doc.WriteTo(writer); 
      writer.Flush(); 
      ms.Position = 0; 
      XmlReader reader = XmlReader.Create(ms); 
      reply = Message.CreateMessage(reader, int.MaxValue, reply.Version); 

     } 

     public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) 
     { 
      string action = request.Headers.GetHeader<string>("Action", request.Headers[0].Namespace); 
      if (action.Contains("GetData")) 
      { 
       XmlDocument doc = new XmlDocument(); 
       MemoryStream ms = new MemoryStream(); 
       XmlWriter writer = XmlWriter.Create(ms); 
       request.WriteMessage(writer); 
       writer.Flush(); 
       ms.Position = 0; 
       doc.Load(ms); 
       ChangeMessage(doc, true); 
       ms.SetLength(0); 
       writer = XmlWriter.Create(ms); 
       doc.WriteTo(writer); 
       writer.Flush(); 
       ms.Position = 0; 
       XmlReader reader = XmlReader.Create(ms); 
       request = Message.CreateMessage(reader, int.MaxValue, request.Version); 
      } 
      request.Headers.Action += "1"; 
      return null; 
     } 

     void ChangeMessage(XmlDocument doc, bool flag) 
     { 
      XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable); 
      nsManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/"); 
      nsManager.AddNamespace("tempuri", "http://tempuri.org/"); 
      XmlNode node = doc.SelectSingleNode("//s:Body", nsManager); 
      if (node != null) 
      { 
       if (flag) 
        node.InnerXml = node.InnerXml.Replace("GetData", "GetData1"); 
       else 
        node.InnerXml = node.InnerXml.Replace("GetData1Response", "GetDataResponse").Replace("GetData1Result", "GetDataResult"); 
      } 
     } 
    } 

    public class MyBehavior : BehaviorExtensionElement, IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
      //endpoint.Behaviors.Add(new MyBehavior()); 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
     { 
      MyInspector inspector = new MyInspector(); 
      clientRuntime.MessageInspectors.Add(inspector); 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
     { 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
     } 

     protected override object CreateBehavior() 
     { 
      return new MyBehavior(); 
     } 

     public override Type BehaviorType 
     { 
      get 
      { 
       Type t = Type.GetType("MethodChangeService.MyBehavior"); 
       return t; 
      } 
     } 
    } 
} 

和服務類:

using System; 
using System.Configuration; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.Text; 
using System.ServiceModel.Description; 
using System.ServiceModel.Configuration; 
using System.ServiceModel.Dispatcher; 
using System.ServiceModel.Channels; 
using System.IO; 
using System.Xml; 

namespace MethodChangeService 
{ 
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together. 
    public class HardcoadedService : IHardcoadedService 
    { 
     public string GetData(int i) 
     { 
      return string.Format("you entered {0}",i); 
     } 

     public string GetData1() 
     { 
      return string.Format("You got redirected to another method!!"); 
     } 
    } 

} 

下面是客戶端代碼:

class Program 
    { 
     static void Main(string[] args) 
     { 
      HardcoadedServiceClient c = new HardcoadedServiceClient(); 
      c.Endpoint.Behaviors.Add(new MyBehavior()); 
      string s = c.GetData(3); 
      Console.WriteLine(s); 
      Console.ReadKey(); 
     } 
    } 

感謝 蘇拉傑

+1

請原諒我是因爲這是一個POC代碼,沒有命名conv,並且都遵循... :-) – user1312242

+1

您可以不使用IDispatchMessageInspector的方法BeforeSendReply和AfterRecieveRequest在您的服務上執行相同的操作(http://msdn.microsoft.com/zh-cn/ -us /庫/ system.servicemodel.dispatcher.idispatchmessageinspector.aspx)。這樣做可以在服務級別使用它,客戶端不需要使用IClientMessageInspector。有關郵件檢查器的更多信息,請訪問:http://msdn.microsoft.com/en-us/library/aa717047.aspx – Rajesh

+0

這是另一個示例:http://stackoverflow.com/questions/29352015/how-can-我創建定製的XML命名空間的屬性,當消耗-A-傳統皁-SE –

回答

6

您可以使用app.config文件中的<behaviors><extensions>部分爲您的客戶端完成此操作。

要註冊您的自定義行爲以下內容添加到您的app.config文件的<system.serviceModel>部分:

<behaviors> 
    <endpointBehaviors> 
    <behavior name="MyBehavior"> 
     <myBehavior/> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 
<extensions> 
    <behaviorExtensions> 
    <add name="myBehavior" type="MethodChangeService.MyBehavior, MethodChangeService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </behaviorExtensions> 
</extensions> 

然後在<endpoint>元素,如果<client>部分添加以下屬性:

behaviorConfiguration="MyBehavior" 

對於更好的說明,結帳這篇文章:Creating Custom WCF Endpoint Behavior