Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net MessageInspector message:";此消息无法支持该操作,因为它已被复制。”;_.net_Wcf - Fatal编程技术网

.net MessageInspector message:";此消息无法支持该操作,因为它已被复制。”;

.net MessageInspector message:";此消息无法支持该操作,因为它已被复制。”;,.net,wcf,.net,Wcf,事情是这样的: 出于跟踪和安全原因,我有一个业务请求,要求所有WCF消息都应有一个特定的头 无论如何,我在客户端和服务上都设置了MessageInspector的实现——到目前为止,我们控制着两端——并且在原型阶段都工作得很好 然而,今天,有些事情发生了,停止了工作 我从头开始重做了原型,一切正常。整个下午我都在为它发疯 有关守则如下: public class DispatchEndpointBehavior : IEndpointBehavior { public void ApplyD

事情是这样的:

出于跟踪和安全原因,我有一个业务请求,要求所有WCF消息都应有一个特定的头

无论如何,我在客户端和服务上都设置了
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;