2012-05-04 4 views
13

내 WCF 서비스에서 IClientMessageInspector의 BeforeSendRequest 및 AfterReceiveReply에서 SOAP를 편집하려고합니다.IClientMessageInspector를 사용하는 WCF 서비스의 SOAP 수정

내가 같이 사용자 정의 동작을 만들었습니다

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

MyInspector로부터 상속 클래스에 불과하다 : 클래스 MyBehavior에서

public class MyBehavior : BehaviorExtensionElement, IEndpointBehavior 
{ 
} 

, 나는 코드를 다음과 같이 IEndpointBehavior 방법을 구현 IClientMessageInspector.

이제 내 질문은 : IEndpointBehavior의 ApplyClientBehavior가 실행되지 않습니다. 그러나 WCF 클라이언트에서, MyBehavior 클래스가 있고 클라이언트 측에서 코드 아래에 쓰기 어디 프로젝트의 참조를 추가 할 때 : 그것은 잘 작동

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

. Apply Client Behavior 메서드가 실행되는 것을 의미합니다.

고객에게이 동작을 수동으로 추가하고 싶지 않으며 자동으로이를 수행하려고합니다. 나는 어떻게 이것을 얻을 수 있습니까? 여기

전체 코드입니다 :

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

감사 SURAJ

+1

변명 나에게 이것은 POC 코드가 아니며 명명 규칙이 없으며 모두 따라야합니다. :-) – user1312242

+1

IDispatchMessageInspector의 BeforeSendReply 및 AfterRecieveRequest 메서드를 사용하여 서비스에서 동일한 작업을 수행 할 수 있습니까? (http://msdn.microsoft.com/en-us/library/ -us/library/system.servicemodel.dispatcher.idispatchmessageinspector.aspx). 그렇게하면 서비스 수준에서 사용할 수 있으며 클라이언트는 IClientMessageInspector를 사용할 필요가 없습니다. 메시지 관리자에 대한 자세한 내용은 다음을 참조하십시오. http://msdn.microsoft.com/en-us/library/aa717047.aspx – Rajesh

+0

다음은이 예제입니다. http://stackoverflow.com/questions/29352015/how-can- i-create-custom-xml-namespace-attributes-consuming-a-legacy-soap-se –

답변

6

당신 클라이언트의 app.config 파일에있는 <behaviors><extensions> 섹션을 사용하여이를 수행 할 수 있습니다. A에 대한

behaviorConfiguration="MyBehavior" 

다음 <client> 섹션은 다음과 같은 속성을 추가 할 경우 <endpoint> 요소에

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

다음 :

사용자 정의 동작은 당신의 app.config 파일의 <system.serviceModel> 섹션에 다음을 추가 등록하려면 더 나은 설명,이 문서 체크 아웃 : Creating Custom WCF Endpoint Behavior