.net MessageInspector message:";此消息无法支持该操作,因为它已被复制。”;
事情是这样的: 出于跟踪和安全原因,我有一个业务请求,要求所有WCF消息都应有一个特定的头 无论如何,我在客户端和服务上都设置了.net MessageInspector message:";此消息无法支持该操作,因为它已被复制。”;,.net,wcf,.net,Wcf,事情是这样的: 出于跟踪和安全原因,我有一个业务请求,要求所有WCF消息都应有一个特定的头 无论如何,我在客户端和服务上都设置了MessageInspector的实现——到目前为止,我们控制着两端——并且在原型阶段都工作得很好 然而,今天,有些事情发生了,停止了工作 我从头开始重做了原型,一切正常。整个下午我都在为它发疯 有关守则如下: public class DispatchEndpointBehavior : IEndpointBehavior { public void ApplyD
MessageInspector
的实现——到目前为止,我们控制着两端——并且在原型阶段都工作得很好
然而,今天,有些事情发生了,停止了工作
我从头开始重做了原型,一切正常。整个下午我都在为它发疯
有关守则如下:
public class DispatchEndpointBehavior : IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
var mi = new MessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(mi);
}
// ...
}
public class DispatchMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
var index = request.Headers.FindHeader("name", "");
if (index == -1)
throw new MessageSecurityException("...");
var value = request.Headers.GetHeader<Guid>(index);
// do something with the value
return null;
}
// ...
}
public class ClientEndpointBehavior : IClientEndpointBehavior
{
public void ApplyClientBehavior(ServiceEndpoint endpoint,
ClientRuntime clientRuntime)
{
var mi = new ClientSecurityMessageInspector();
clientRuntime.MessageInspectors.Add(mi);
}
// ...
}
public class ClientSecurityMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request,
IClientChannel channel)
{
request.Headers.Add(MessageHeader.CreateHeader("name", "", Guid.NewGuid()));
return null;
}
// ...
}
编辑以添加
正如我在其中一条评论中所说,我在这里发布了一个原型项目:
我再强调也不为过原型的工作。我唯一不知道的是为什么我突然开始收到这个奇怪的信息。我不复制消息,只处理标题,我搜索的每一个地方都说阅读消息是一个大禁忌
我害怕这样一个事实,即在WCF模型中有如此多的点需要检查,甚至需要替换整个信息,建筑师设计了这样一个对象,即使你看它,它也会失效
如果你给了检查的机会,制作一个坚固的对象,它可以承受任何想要检查它的人操纵它的痛苦。这是因为消息对象只能读取一次。尝试使用缓冲区副本:
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
MessageBuffer buffer = reply.CreateBufferedCopy(MaxMessageSize);
Message requestCopy = buffer.CreateMessage();
var index = requestCopy.Headers.FindHeader("name", "");
if (index == -1)
throw new MessageSecurityException("...");
var value = requestCopy.Headers.GetHeader<Guid>(index);
// do something with the value
return null;
}
接收方请求后的公共对象(参考消息请求,
IClientChannel频道,
InstanceContext(InstanceContext)
{
MessageBuffer=reply.CreateBufferedCopy(MaxMessageSize);
Message requestCopy=buffer.CreateMessage();
var index=requestCopy.Headers.FindHeader(“名称”,“名称”);
如果(索引==-1)
抛出新MessageSecurityException(“…”);
var值=requestCopy.Headers.GetHeader(索引);
//做一些有价值的事情
返回null;
}
有关更多信息,请查看。使用Greg Sansoms解决方案,但将原始邮件替换为原始邮件的副本:
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
MessageBuffer buffer = request.CreateBufferedCopy(MaxMessageSize);
Message requestCopy = buffer.CreateMessage();
var index = requestCopy.Headers.FindHeader("name", "");
if (index == -1)
throw new MessageSecurityException("...");
var value = requestCopy.Headers.GetHeader<Guid>(index);
// do something with the value
//make sure the orignal message is set to a value wich has not been copied nor read
request = buffer.createMessage();
return null;
接收方请求后的公共对象(参考消息请求,
IClientChannel频道,
InstanceContext(InstanceContext)
{
MessageBuffer=request.CreateBufferedCopy(MaxMessageSize);
Message requestCopy=buffer.CreateMessage();
var index=requestCopy.Headers.FindHeader(“名称”,“名称”);
如果(索引==-1)
抛出新MessageSecurityException(“…”);
var值=requestCopy.Headers.GetHeader(索引);
//做一些有价值的事情
//确保原始消息设置为未被复制或读取的值
request=buffer.createMessage();
返回null;
}
确保通过ref传递请求对象异常堆栈跟踪是什么?问题是消息没有到达服务器。它甚至没有离开客户。我不知道发生了什么事。我甚至从头开始重做了原型机,在原型机中它就像一个符咒。@Paulo:你确定没有什么东西离开客户吗?(如果是,您如何确定?)堆栈跟踪表明客户端堆栈收到了来自服务器的故障响应。您是否在客户端和服务器上都配置了WCF跟踪?这始终是诊断任何意外行为的良好第一步?@Paolo:您是否确认MessageInspector导致了问题?如果你拿走了MessageInspector,一切都正常吗。如果我删除
MI
一切正常。我创建了一个运行良好的原型,我将很快在这里发布。request=buffer.createMessage()代码>非常重要
(System.ServiceModel.FaultException) This message cannot support the operation because it has been copied.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ConsoleApplication1.UserManagementService.IUserManagement.CreateUser(String username, String password, String[] systemCodes)
at ConsoleApplication1.UserManagementService.UserManagementClient.CreateUser(String username, String password, String[] systemCodes) in C:\Users\Paulo Santos\Documents\Visual Studio 2008\Projects\PJonDevelopment\ConsoleApplication1\ConsoleApplication1\Service References\UserManagementService\Reference.cs
at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Paulo Santos\Documents\Visual Studio 2008\Projects\PJonDevelopment\ConsoleApplication1\ConsoleApplication1\Program.cs
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
MessageBuffer buffer = reply.CreateBufferedCopy(MaxMessageSize);
Message requestCopy = buffer.CreateMessage();
var index = requestCopy.Headers.FindHeader("name", "");
if (index == -1)
throw new MessageSecurityException("...");
var value = requestCopy.Headers.GetHeader<Guid>(index);
// do something with the value
return null;
}
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
MessageBuffer buffer = request.CreateBufferedCopy(MaxMessageSize);
Message requestCopy = buffer.CreateMessage();
var index = requestCopy.Headers.FindHeader("name", "");
if (index == -1)
throw new MessageSecurityException("...");
var value = requestCopy.Headers.GetHeader<Guid>(index);
// do something with the value
//make sure the orignal message is set to a value wich has not been copied nor read
request = buffer.createMessage();
return null;