2011-12-29 298 views
1

我有定製IClientMessageFormatter,目前增加歸因於指定的XML元素消息:無法獲得IClientMessageFormatter工作

public class GetOrdersMessageFormatter : IClientMessageFormatter 
{ 
    readonly IClientMessageFormatter original; 

    public GetOrdersMessageFormatter(IClientMessageFormatter actual) 
    { 
     original = actual; 
    } 

    public void AddArrayNamespace(XmlNode node) 
    { 
     if (node != null) 
     { 
      var attribute = node.OwnerDocument.CreateAttribute("test"); 
      attribute.Value = "test"; 
      node.Attributes.Append(attribute); 
     } 
    }  

    public object DeserializeReply(Message message, object[] parameters) 
    { 
     return original.DeserializeReply(message, parameters); 
    } 

    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) 
    { 
     Message newMessage = null; 

     var message = original.SerializeRequest(messageVersion, parameters); 

     if (message.Headers.Action == "urn:Mage_Api_Model_Server_HandlerAction") 
     { 
      var doc = new XmlDocument(); 

      using (var reader = message.GetReaderAtBodyContents()) 
      { 
       doc.Load(reader); 
      } 

      if (doc.DocumentElement != null) 
      { 
       switch (doc.DocumentElement.LocalName) 
       { 
        case "call": 
         AddArrayNamespace(doc.SelectSingleNode("//args")); 
         break; 
       } 
      } 

      using (var ms = new MemoryStream()) 
      { 
       using (var xw = XmlWriter.Create(ms)) 
       { 
        doc.Save(xw);      

        ms.Position = 0; 
        using (var xr = XmlReader.Create(ms)) 
        { 
         newMessage = Message.CreateMessage(message.Version, null, xr); 
         newMessage.Headers.CopyHeadersFrom(message); 
         newMessage.Properties.CopyProperties(message.Properties); 
        } 
       } 
      } 
     } 

     return newMessage; 
    }  
} 

它給例外

System.ArgumentException:該用於消息正文的XmlReader必須位於元素上。 參數名:讀者

服務器堆棧跟蹤:在在System.ServiceModel.Channels System.ServiceModel.Channels.BodyWriter.WriteBodyContents(的XmlDictionaryWriter作家) 在System.ServiceModel.Channels.XmlReaderBodyWriter.OnWriteBodyContents(的XmlDictionaryWriter作家) .BodyWriterMessage.OnWriteBodyContents(的XmlDictionaryWriter作家) 在System.ServiceModel.Channels.Message.OnWriteMessage(的XmlDictionaryWriter作家) 在System.ServiceModel.Channels.Message.WriteMessage(的XmlDictionaryWriter作家) 在System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(消息消息,BufferManager bufferManager,Int32 initialOffset,Int32 maxSizeQuota) 在System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(消息消息的Int32 maxMessageSize,BufferManager bufferManager,的Int32 messageOffset) 在System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(消息信息) 在System.ServiceModel.Channels.HttpOutput 。發送(時間跨度超時) 在System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.SendRequest(消息消息,時間跨度超時) 在System.ServiceModel.Channels.RequestChannel.Request(消息消息,時間跨度超時) 在系統。 ServiceModel.Dispatcher.RequestChannelBinder.Request(消息消息,TimeSpan超時) at System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins ,對象[]奏,時間跨度超時) 在System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage包括MethodCall,ProxyOperationRuntime操作) 在System.ServiceModel.Channels.ServiceChannelProxy.Invoke(即時聊天消息)

我想,這可能是我需要使用message.CreateBufferedCopy()創建郵件副本並使用該副本來加載XmlDocument,但這也沒有奏效。 可能有人知道我做錯了什麼,或知道例子,這是做了非常相同的事情(我的意思是在發送之前影響消息xml)。

回答

3

格式化程序中的問題在於,您正在使用在消息消耗之前放置的閱讀器(和流)創建消息。從創建流和閱讀器中刪除「使用」語句後,請求就會經過 - 請參閱下面的代碼。

public class StackOverflow_8669406 
{ 
    public class GetOrdersMessageFormatter : IClientMessageFormatter 
    { 
     readonly IClientMessageFormatter original; 

     public GetOrdersMessageFormatter(IClientMessageFormatter actual) 
     { 
      original = actual; 
     } 

     public void AddArrayNamespace(XmlNode node) 
     { 
      if (node != null) 
      { 
       var attribute = node.OwnerDocument.CreateAttribute("test"); 
       attribute.Value = "test"; 
       node.Attributes.Append(attribute); 
      } 
     } 

     public object DeserializeReply(Message message, object[] parameters) 
     { 
      return original.DeserializeReply(message, parameters); 
     } 

     public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) 
     { 
      Message newMessage = null; 

      var message = original.SerializeRequest(messageVersion, parameters); 

      if (message.Headers.Action == "urn:Mage_Api_Model_Server_HandlerAction") 
      { 
       var doc = new XmlDocument(); 

       using (var reader = message.GetReaderAtBodyContents()) 
       { 
        doc.Load(reader); 
       } 

       if (doc.DocumentElement != null) 
       { 
        switch (doc.DocumentElement.LocalName) 
        { 
         case "call": 
          AddArrayNamespace(doc.SelectSingleNode("//args")); 
          break; 
        } 
       } 

       var ms = new MemoryStream(); 

       XmlWriterSettings ws = new XmlWriterSettings 
       { 
        CloseOutput = false, 
       }; 

       using (var xw = XmlWriter.Create(ms, ws)) 
       { 
        doc.Save(xw); 
        xw.Flush(); 
       } 

       Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 

       ms.Position = 0; 
       var xr = XmlReader.Create(ms); 
       newMessage = Message.CreateMessage(message.Version, null, xr); 
       newMessage.Headers.CopyHeadersFrom(message); 
       newMessage.Properties.CopyProperties(message.Properties); 
      } 

      return newMessage; 
     } 
    } 

    [ServiceContract(Namespace = "")] 
    public interface ITest 
    { 
     [OperationContract(Action = "urn:Mage_Api_Model_Server_HandlerAction")] 
     int call(string args); 
    } 
    public class Service : ITest 
    { 
     public int call(string args) 
     { 
      return int.Parse(args); 
     } 
    } 
    class MyBehavior : IOperationBehavior 
    { 
     public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 
     { 
      clientOperation.Formatter = new GetOrdersMessageFormatter(clientOperation.Formatter); 
     } 

     public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 
     { 
     } 

     public void Validate(OperationDescription operationDescription) 
     { 
     } 
    } 
    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), ""); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress)); 
     foreach (OperationDescription operation in factory.Endpoint.Contract.Operations) 
     { 
      operation.Behaviors.Add(new MyBehavior()); 
     } 

     ITest proxy = factory.CreateChannel(); 
     Console.WriteLine(proxy.call("4455")); 

     ((IClientChannel)proxy).Close(); 
     factory.Close(); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
}