【问题标题】:EDIT SOAP of a WCF Service using IClientMessageInspector使用 IClientMessageInspector 编辑 WCF 服务的 SOAP
【发布时间】:2012-05-04 11:52:39
【问题描述】:

在我的 WCF 服务中,我想在 IClientMessageInspector 的 BeforeSendRequest 和 AfterReceiveReply 中编辑 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());

它工作正常。我的意思是 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();
        }
    }

【问题讨论】:

标签: wcf soap


【解决方案1】:

您可以使用您客户的 app.config 文件中的 &lt;behaviors&gt;&lt;extensions&gt; 部分来完成此操作。

要注册您的自定义行为,请将以下内容添加到您的 app.config 文件的 &lt;system.serviceModel&gt; 部分:

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

然后在&lt;endpoint&gt; 元素中如果&lt;client&gt; 部分添加以下属性:

behaviorConfiguration="MyBehavior"

有关更多信息,请查看:Configuring and Extending the Runtime with Behaviors

【讨论】:

    猜你喜欢
    • 2011-08-05
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多