在为WCF REST服务的自定义(反)序列化实现IDispatchMessageFormatter时,如何读取Message对象的主体?

时间:2011-05-10 17:07:42

标签: wcf json serialization wcf-binding

我正在扩展WebHttpBehavior以展示带有自定义序列化和反序列化的WCF REST服务(以及与该问题无关的一定数量的其他功能)。

新行为使用IDispatchMessageFormatter的实现来执行服务所服务的POCO的自定义序列化和反序列化,并通过SerializeReplyDeserializeRequest方法发送给它。

我可以在SerializeReply中完全按照我的需要提供XML和JSON。

我可以毫无问题地反序列化XML,但是我似乎无法找到反序列化JSON消息的方法,因为我无法获取DeserializeRequest DeserializeRequest参数中包含的纯文本

这就是if (format == System.ServiceModel.Web.WebMessageFormat.Json) { var data = ""; // TODO obtain plain text from Message object var json = JsonConvert.DeserializeObject(data, paramType, new IsoDateTimeConverter(), new StringEnumConverter()); parameters[paramIndex] = json; } else { var serializer = new System.Xml.Serialization.XmlSerializer(paramType, string.Empty); var reader = message.GetReaderAtBodyContents(); parameters[paramIndex] = serializer.Deserialize(reader); } 中的代码现在的样子:

Message

我正在使用Message进行JSON(反)序列化。

有关如何从{{1}}对象获取纯文本以便反序列化的任何建议,我们将不胜感激。

如果您认为我的方法有问题,我也希望在评论中听到它。

2 个答案:

答案 0 :(得分:13)

您需要确保将消息的WebMessageFormat设置为原始,否则WCF将使用JsonMessageEncoder来创建Message而这反过来将不允许您获取原始邮件内容。

您可以通过实施自定义WebContentTypeMapper

来实现这一目标
public class RawMapper : WebContentTypeMapper
{
    public override WebContentFormat GetMessageFormatForContentType(string contentType)
    {
        return WebContentFormat.Raw;
    }
}

...需要应用于WebHttpBinding:

webHttpBinding.ContentTypeMapper = new RawMapper();

..或通过配置:

<bindings>
  <webHttpBinding>
    <binding contentTypeMapper="Samples.RawMapper, MyContentTypeMapperAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </webHttpBinding>
</bindings>

有了这个,你就可以像下面那样检索请求体:

    public void DeserializeRequest(Message message, object[] parameters)
    {
        var bodyReader = message.GetReaderAtBodyContents();
        bodyReader.ReadStartElement("Binary");
        byte[] rawBody = bodyReader.ReadContentAsBase64();

        string messageAsString;
        using (var reader = new StreamReader(new MemoryStream(rawBody)))
            messageAsString = reader.ReadToEnd();

        object jsonObj = JsonConvert.DeserializeObject(messageAsString);

        parameters[0] = jsonObj;
    }

答案 1 :(得分:3)

即使您使用的是WebMessageFormat.Json,也可以将消息转换为字符串,然后将其反序列化为DeserializeRequest方法中的对象。

MemoryStream mss = new MemoryStream();
XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(mss);
message.WriteMessage(writer);
writer.Flush();
string messageBody = Encoding.UTF8.GetString(mss.ToArray());

var obj = JsonConvert.DeserializeObject(messageBody, operation.Messages[0].Body.Parts[0].Type);

parameters[0] = obj;