在实现 IDispatchMessageFormatter 以进行 WCF REST 服务的自定义(反)序列化时,如何读取 Message 对象的正文?

发布于 2024-11-05 22:03:41 字数 1910 浏览 1 评论 0原文

我正在扩展 WebHttpBehavior 公开具有自定义序列化和反序列化的 WCF REST 服务(加上与问题无关的一定数量的其他功能)。

新行为使用 IDispatchMessageFormatter对服务提供的 POCO 执行自定义序列化和反序列化,并通过 SerializeReply 和<一href="http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.idispatchmessageformatter.deserializerequest.aspx" rel="nofollow">DeserializeRequest 方法。

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

我可以毫无问题地反序列化 XML,但是我似乎找不到反序列化 JSON 消息的方法,因为我无法获取 DeserializeRequestMessage 参数。

这就是 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);
}

我正在使用 Json.NET 用于 JSON(反)序列化。

任何有关如何从 Message 对象获取纯文本以反序列化它的建议将不胜感激。

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

I am extending WebHttpBehavior to expose a WCF REST service with customized serialization and deserialization (plus a certain number of other features that are not relevant to the problem).

The new behavior uses an implementation of IDispatchMessageFormatter to perform custom serialization and deserialization of POCOs served by the service and sent to it thanks to the SerializeReply and DeserializeRequest methods.

I can serve XML and JSON exactly how I need them in SerializeReply.

I can deserialize XML without a problem, however I can't seem to find the way to deserialize a JSON message because I can't obtain the plain text contained in the Message parameter of DeserializeRequest.

This is what the code in DeserializeRequest looks like right now:

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);
}

I'm using Json.NET for JSON (de)serialization.

Any suggestions on how to obtain plain text from the Message object in order to deserialize it would be greatly appreciated.

If you think there's something wrong in my approach I'd also like to hear of it in the comments.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水溶 2024-11-12 22:03:41

您需要确保消息的 WebMessageFormat 设置为 Raw,否则 WCF 将使用 JsonMessageEncoder 来创建 < code>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;
    }

You need to make sure that the WebMessageFormat of the Message is set to Raw, otherwise WCF will use a the JsonMessageEncoder in order to create the Message which in turn won't allow you to get to the raw message content.

You do that by implementing a custom WebContentTypeMapper:

public class RawMapper : WebContentTypeMapper
{
    public override WebContentFormat GetMessageFormatForContentType(string contentType)
    {
        return WebContentFormat.Raw;
    }
}

...which needs to be applied to the WebHttpBinding:

webHttpBinding.ContentTypeMapper = new RawMapper();

..or via configuration:

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

With that in place, you can then retrieve the request body as a String like that:

    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;
    }
神妖 2024-11-12 22:03:41

即使您使用的是 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;

Even if you are using WebMessageFormat.Json you can convert your message to string and then deserialize it to object inside DeserializeRequest method.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文