我实现了一个自定义消息检查器(通过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(在反序列化的对象中)。
答案 0 :(得分:5)
请求对象包含WCF消息头和有效负载。您需要剥离标题,然后您应该能够反序列化邮件正文。
例如,SOAP消息将具有:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
</soap:Header>
<soap:Body>
<!-- your payload -->
</soap:Body>
您可以使用XML导航来访问body元素,然后单独反序列化该元素。
编辑: 实际上我只是偶然发现了这个方法,我觉得应该为你做的伎俩:
答案 1 :(得分:0)
我刚刚这样做了。只需将以下所有代码粘贴到您的课程中,然后调用 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;
}
答案 2 :(得分:-3)
我最终走上了消息标题路线,就像Mike Parkhill建议的那样。