在我的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();
}
}
感謝 蘇拉傑
請原諒我是因爲這是一個POC代碼,沒有命名conv,並且都遵循... :-) – user1312242
您可以不使用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
這是另一個示例:http://stackoverflow.com/questions/29352015/how-can-我創建定製的XML命名空間的屬性,當消耗-A-傳統皁-SE –