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

时间:2018-09-28 15:34:31

标签: c# json web-services wcf

我需要支持将数据发布到我们的WCF服务中,其内容类型为x-www-form-urlencoded。由于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)
    { }
}

我得到的错误:

  

请求错误服务器在处理请求时遇到错误。   异常消息为“预期状态为'元素'。。   名称为“,名称空间为”的“文本”。 '。

1 个答案:

答案 0 :(得分:0)

所以,看来我实际上并没有很好地说明我实际上要完成的工作,但是在与之抗争之后,我终于弄清楚了。

我得到的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内容类型中的帖子。