2012-05-04 24 views
13

Trong dịch vụ WCF của tôi, tôi muốn chỉnh sửa SOAP trong BeforeSendRequest và AfterReceiveReply của IClientMessageInspector.EDIT SOAP của một dịch vụ WCF bằng cách sử dụng IClientMessageInspector

tôi đã tạo ra một hành vi tùy chỉnh như thế này:

public class MyBehavior : BehaviorExtensionElement, IEndpointBehavior 
{ 
} 

trong lớp MyBehavior, tôi thực hiện phương pháp IEndpointBehavior Giống như bên dưới mã:

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

MyInspector là gì, nhưng các lớp được thừa kế từ IClientMessageInspector.

Bây giờ, câu hỏi của tôi là: ApplyClientBehavior của IEndpointBehavior không bị sa thải. Nhưng tại wcf khách hàng, khi tôi thêm một tham chiếu của dự án nơi lớp MyBehavior là hiện tại và viết bên dưới mã ở phía khách hàng:

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

Nó hoạt động tốt. Tôi có nghĩa là phương pháp áp dụng hành vi khách hàng bị sa thải.

Tôi không muốn yêu cầu khách hàng của mình thêm Hành vi này theo cách thủ công và tôi muốn điều này xảy ra tự động. Làm thế nào tôi có thể đạt được điều này?

Đây là mã đầy đủ:

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; 
      } 
     } 
    } 
} 

và lớp dịch vụ là:

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!!"); 
     } 
    } 

} 

Đây là mã khách hàng:

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(); 
     } 
    } 

Cảm ơn Suraj

+1

Xin lỗi tôi vì đây là một POC Mã không đặt tên conv và tất cả được theo sau ... :-) – user1312242

+1

Bạn có thể không thực hiện giống nhau trên dịch vụ của bạn với các phương pháp BeforeSendReply và AfterRecieveRequest của IDispatchMessageInspector (http://msdn.microsoft.com/en -us/library/system.servicemodel.dispatcher.idispatchmessageinspector.aspx). Làm như vậy bạn có thể sử dụng nó ở cấp độ dịch vụ của bạn và khách hàng sẽ không cần sử dụng IClientMessageInspector. Thông tin thêm về thanh tra thư tại đây: http://msdn.microsoft.com/en-us/library/aa717047.aspx – Rajesh

+0

Đây là một ví dụ khác về điều này: http://stackoverflow.com/questions/29352015/how-can- i-create-custom-xml-namespace-attributes-khi-tiêu thụ-a-legacy-soap-se –

Trả lời

6

Bạn có thể thực hiện việc này bằng cách sử dụng các phần <behaviors><extensions> trong tệp app.config cho khách hàng của bạn.

Để đăng ký hành vi tùy chỉnh của bạn thêm dòng sau vào phần <system.serviceModel> của app.config tập tin của bạn:

<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> 

Sau đó, trong <endpoint> yếu tố nếu phần <client> thêm thuộc tính sau:

behaviorConfiguration="MyBehavior" 

Đối với một giải thích tốt hơn, hãy kiểm tra bài viết này: Creating Custom WCF Endpoint Behavior

Các vấn đề liên quan