如何将 x-www-form-urlencoded post Message 转换为 JSON post Message?

Posted

技术标签:

【中文标题】如何将 x-www-form-urlencoded post Message 转换为 JSON post Message?【英文标题】:How to convert x-www-form-urlencoded post Message to JSON post Message? 【发布时间】:2019-03-04 15:26:57 【问题描述】:

我需要支持以x-www-form-urlencoded 的内容类型将数据发布到我们的 WCF 服务。由于 WCF 本身不喜欢这样做,所以我的想法是使用 MessageInspector 来拦截具有该内容类型的传入消息,读出正文,将其转换为 JSON 字符串,然后替换请求消息。

问题是我似乎无法创建我的服务真正喜欢的新 Message 对象。我可以获取正文并将其转换为 JSON 字符串就好了,但是我创建的新消息会导致错误,而不是通过适当的服务方法。

这是我目前所拥有的。我已经修补了一天又一点,尝试了几种不同的方法,但运气不佳。我将在当前遇到的错误下方发布。

我要调用的Web服务方法:

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/PostTest", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public string PostTest(TestObject thinger)

    return thinger.Thing;

消息检查器:

public class FormPostConverter : IDispatchMessageInspector

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    
        var contentType = (request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers["Content-Type"];

        if (!request.IsEmpty && contentType == "application/x-www-form-urlencoded")
        
            var body = HttpUtility.ParseQueryString(new StreamReader(request.GetBody<Stream>()).ReadToEnd());
            var json = new javascriptSerializer().Serialize(body.AllKeys.ToDictionary(k => k, k => body[k]));

            Message newMessage = Message.CreateMessage(MessageVersion.None, "", json, new DataContractJsonSerializer(typeof(string)));
            newMessage.Headers.CopyHeadersFrom(request);
            newMessage.Properties.CopyProperties(request.Properties);
            (newMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers.Set(HttpRequestHeader.ContentType, "application/json");
            newMessage.Properties[WebBodyFormatMessageProperty.Name] = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            request = newMessage;
        

        return null;
    

    public void BeforeSendReply(ref Message reply, object correlationState)
     

我得到的错误:

请求错误 服务器在处理请求时遇到错误。 异常消息是 'Expecting state 'Element'.. 遇到 “文本”,名称为“”,命名空间为“”。 '。

【问题讨论】:

在你走得更远之前,json 内容与 x-www-form-urlencoded 不同。你是说 application/json 吗? 是的,我的意思是应用程序/json。 【参考方案1】:

所以,我似乎并没有很好地表达我真正想要完成的事情,但在与它斗争了一些之后,我终于弄明白了。

我生成的 MessageInspector 如下所示:

public class FormPostConverter : IDispatchMessageInspector

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    
        var contentType = (request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers["Content-Type"];

        if (!request.IsEmpty && contentType == "application/x-www-form-urlencoded")
        
            var body = HttpUtility.ParseQueryString(new StreamReader(request.GetBody<Stream>()).ReadToEnd());
            if (body != null && body.HasKeys())
            
                Message newMessage = Message.CreateMessage(MessageVersion.None, "", new XElement("root", body.AllKeys.Select(o => new XElement(o, body[o]))));
                newMessage.Headers.CopyHeadersFrom(request);
                newMessage.Properties.CopyProperties(request.Properties);
                (newMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty)?.Headers.Set(HttpRequestHeader.ContentType, "application/json");
                newMessage.Properties[WebBodyFormatMessageProperty.Name] = new WebBodyFormatMessageProperty(WebContentFormat.Json);
                request = newMessage;
            
        

        return true;
    

    public void BeforeSendReply(ref Message reply, object correlationState)
     

事实证明,我真正需要做的只是将我的主体转换为 XML 元素,而不是尝试将其转换为 JSON。在检查了一个以 JSON 形式出现的有效 POST 后,我看到在这个阶段它已经在 Message 对象中转换为 XML。

有了这个,我可以正常编写我的服务方法(没有 Stream 参数和手动解析),并在 application/json 或 x-www-form-urlencoded 内容类型中接受发给它们的帖子。

【讨论】:

以上是关于如何将 x-www-form-urlencoded post Message 转换为 JSON post Message?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Content-Type: application/x-www-form-urlencoded 格式的数据帧行迭代到 API POST 请求中?

将 json 转换为 x-www-form-urlencoded

如何在 SoapUI 中设置 x-www-form-urlencoded?

如何使用内容类型 ='application/x-www-form-urlencoded' 在 node.js 中发布数据

在 Postman 中将 JSON 嵌套节点转换为 x-www-form-urlencoded

如何使用 Angular $resource 发送 x-www-form-urlencoded 数据?