您可以试试这个,我以前从未更改过消息,所以我不确定它是否完全像这样工作,但我这样做是为了记录消息。
实现一个消息监听器。您有机会处理 BeforeSendReply 方法,您可以在其中访问消息并能够更改它。
然后用属性[MessageListenerBehavior]装饰你的合约实现类
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace YourNamespace
{
public class MessageListenerBehavior : Attribute, IDispatchMessageInspector, IServiceBehavior
{
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Message msg = reply.CreateBufferedCopy(int.MaxValue).CreateMessage();
try
{
//Setup StringWriter to use as input for our StreamWriter
//This is needed in order to capture the body of the message, because the body is streamed.
using (StringWriter stringWriter = new StringWriter())
using (XmlWriter xmlTextWriter = XmlWriter.Create(stringWriter))
{
msg.WriteMessage(xmlTextWriter);
xmlTextWriter.Flush();
xmlTextWriter.Close();
string thexml = stringWriter.ToString();
XDocument doc = XDocument.Parse(thexml);
// alter the doc here...........
Message newMsg = Message.CreateMessage(MessageVersion.Soap11, "http://..something", doc.ToString());
reply = newMsg;
}
catch (Exception ex) { //handle it }
}
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (var endpoint in dispatcher.Endpoints)
{
endpoint.DispatchRuntime.MessageInspectors.Add(new MessageListenerBehavior());
}
}
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
//throw new NotImplementedException();
}
}
public class WcfMessgeLoggerExtension : BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(MessageListenerBehavior);
}
}
protected override object CreateBehavior()
{
return new MessageListenerBehavior();
}
}
}
当您执行Message.CreateMessage 时,我不知道Action 参数在回复中的重要性,但您可以阅读有关如何构建它的值:
Use the Actionproperty to control the action of the method's input message. Because WCF uses this action to dispatch an incoming message to the appropriate method, messages used within a contract operation must have unique actions. The default action value is a combination of the contract namespace (the default value is "http://tempuri.org/"), the contract name (interface name or the class name, if no explicit service interface is used), the operation name, and an additional string ("Response") if the message is a correlated response. You can override this default with the Action property.
更新
我在system.serviceModel 配置中也有这些项目:
<serviceBehaviors>
<behavior name="MessageListenerBehavior">
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
...
<services>
<service behaviorConfiguration="MessageListenerBehavior" name="... your service name...">
...