在服务器上反序列化WCF消息

我实现了一个自定义消息检查器(通过IDispatchMessageInspector)来拦截在WCF服务的服务器端接收的消息,因此我可以尝试反序列化消息并应用一些特定的业务逻辑。 我遇到的问题是当我将MessageBuffer的内容写入新的MemoryStream然后尝试反序列化时,我收到一条错误,上面写着“根级别的数据无效。第1行,第1行”。 我知道传入的数据是有效的,因为跳过检查器可以使一切正常。

示例代码:

public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) { MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); request = buffer.CreateMessage(); string msg = buffer.CreateMessage().ToString(); var dc = new DataContractSerializer(typeof(Adder)); using (var stream = new MemoryStream()) { buffer.WriteMessage(stream); stream.Position = 0; //deserializing error occurs here var c = dc.ReadObject(stream); } return null; } 

这是Adder类/接口:

  [DataContract(Name = "adder", Namespace = "http://test.com")] public class Adder { [DataMember(Name = "first")] public int First { get; set; } [DataMember(Name = "second")] public int Second { get; set; } } [ServiceContract(Namespace = "http://test.com")] public interface ITestSvc { [OperationContract(Name = "add")] int Add(Adder adder); } 

有什么建议或有更好的选择吗? 我的主要目标是在进入我的服务的每个WCF请求中读取XML(在反序列化的对象中)。

请求对象包含WCF消息头和有效负载。 您需要剥离标题,然后您应该能够反序列化邮件正文。

例如,SOAP消息将具有:

        

您可以使用XML导航来获取body元素,然后单独反序列化该元素。

编辑:实际上只是偶然发现了这个方法,我认为应该为你做的伎俩:

Message.GetReaderAtBodyContents

我刚刚这样做了 只需将以下所有代码粘贴到您的类中,然后调用DeserializedResponse()即可 。 您需要将MyResponseObject更改为您尝试反序列化的任何对象的名称。 此外,您需要将“ _requestInspector.Response ”替换为您自己的响应xml字符串变量。 GetSoapBodyInnerXml()方法将剥离Soap Envelope,并仅返回您希望反序列化的响应xml。

  private MyResponseObject DeserializedResponse() { var rootAttribute = new XmlRootAttribute("MyResponseObject "); rootAttribute.Namespace = @"http://www.company.com/MyResponseObjectNamespace"; XmlSerializer serializer = new XmlSerializer(typeof(MyResponseObject ), rootAttribute); string responseSoapBodyInnerXml = GetSoapBodyInnerXml(_requestInspector.Response); AddXmlDeclaration(ref responseSoapBodyInnerXml); MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(responseSoapBodyInnerXml)); MyResponseObject resultingResponse = (MyResponseObject )serializer.Deserialize(memStream); return resultingResponse; } private string GetSoapBodyInnerXml(string soapMessage) { XDocument xDoc = XDocument.Parse(soapMessage); XNamespace nsSoap = @"http://schemas.xmlsoap.org/soap/envelope/"; return xDoc.Descendants(nsSoap + CONST_SoapBody).Descendants().First().ToString(); } private void AddXmlDeclaration(ref string xmlString) { XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlString); //Create an XML declaration. XmlDeclaration xmldecl; xmldecl = doc.CreateXmlDeclaration("1.0", "UTF-8", null); //Add the new node to the document. XmlElement root = doc.DocumentElement; doc.InsertBefore(xmldecl, root); //Return updated xmlString with XML Declaration xmlString = doc.InnerXml; } 

我最终走了消息标题路线,就像Mike Parkhill建议的那样。