2012-05-04 8 views
13

Nel servizio WCF, desidero modificare SOAP in BeforeSendRequest e AfterReceiveReply di IClientMessageInspector.MODIFICA SOAP di un servizio WCF che utilizza IClientMessageInspector

Ho creato un comportamento personalizzato come questo:

public class MyBehavior : BehaviorExtensionElement, IEndpointBehavior 
{ 
} 

nella classe MyBehavior, ho implementato il metodo IEndpointBehavior come sottostante Codice:

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

MyInspector non è altro che la classe che viene ereditato da IClientMessageInspector.

Ora la mia domanda è: ApplyClientBehavior of IEndpointBehavior non viene generato. Ma al client WCF, quando aggiungo un punto di riferimento del progetto in cui è presente la classe MyBehavior e scrivere sotto il codice a lato client:

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

Funziona benissimo. Intendo che il metodo Applica comportamento client viene licenziato.

Non voglio chiedere ai miei clienti di aggiungere questo comportamento manualmente e voglio che questo accada automaticamente. Come posso ottenere questo?

Ecco il codice completo:

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

e la classe di servizio è:

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

} 

Ecco il codice del client:

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

Grazie Suraj

+1

Si prega di scusa in quanto questo è un codice POC senza nomi conv e tutti sono seguiti ... :-) – user1312242

+1

Non si può eseguire lo stesso sul proprio servizio con i metodi BeforeSendReply e AfterRecieveRequest di IDispatchMessageInspector (http://msdn.microsoft.com/en -us/library/system.servicemodel.dispatcher.idispatchmessageinspector.aspx). In questo modo è possibile utilizzarlo a livello di servizio e il client non dovrà utilizzare IClientMessageInspector. Ulteriori informazioni su Message Inspector qui: http://msdn.microsoft.com/en-us/library/aa717047.aspx – Rajesh

+0

Ecco un altro esempio di questo: http://stackoverflow.com/questions/29352015/how-can- custom-namespace XML-attributi-quando-consumo-a-legacy-sapone-se i-CREATE- –

risposta

6

tu è possibile farlo utilizzando le sezioni <behaviors> e <extensions> nel file app.config per il proprio client.

Per registrare il comportamento personalizzato aggiungere quanto segue alla sezione <system.serviceModel> del app.config del file:

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

Poi nel <endpoint> elemento se la sezione <client> aggiungere il seguente attributo:

behaviorConfiguration="MyBehavior" 

Per un migliore spiegazione, controlla questo articolo: Creating Custom WCF Endpoint Behavior

Problemi correlati