How to convert x-www-form-urlencoded post Message to JSON post Message?

BRW

I have a requirement to support data being posted to our WCF service with a content type of x-www-form-urlencoded. Since WCF doesn't like to do that natively, the thought I had was to use a MessageInspector to intercept incoming messages with that content type, read out the body, convert it to a JSON string, and replace the request message.

Problem is that I can't seem to make a new Message object that my service actually likes. I can get the body and turn it into a JSON string just fine, but the new message I create causes errors instead of going on through to the appropriate service method.

This is what I've got currently. I've been tinkering with this for a day and a bit now, trying a few different ways, but have had little luck. I'll post below the error I'm currently getting.

Web service method I want to call:

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

The message inspector:

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

The error I'm getting:

Request Error The server encountered an error processing the request. The exception message is 'Expecting state 'Element'.. Encountered 'Text' with name '', namespace ''. '.

BRW

So, it seems I wasn't really wording very well what I was actually trying to accomplish, but after fighting with it some more I did finally figure it out.

My resulting MessageInspector looks like this:

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

Turns out all I really needed to be doing different was turning my body into XML elements instead of trying to do it as JSON. After inspecting a functioning POST that came in as JSON to begin with, I saw that at this stage it had already been turned into XML in the Message object.

With this, I'm able to write my service methods normally (no Stream parameters and manually parsing out) and accept posts to them in application/json or in x-www-form-urlencoded content type.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Convert encoded application/x-www-form-urlencoded post data to json object

how to post body x-www-form-urlencoded using webclient?

How to POST x-www-form-urlencoded in retrofit

How to send post request with x-www-form-urlencoded body

How to POST content as application/x-www-form-urlencoded

How to send x-www-form-urlencoded in a post request in webclient?

How to get and parse JSON response from x-www-form-urlencoded POST, RestTemplate (Java)?

How to post (x-www-form-urlencoded) Json Data using Retrofit?

How to convert x-www-form-urlencoded string to json in dart?

Convert json to x-www-form-urlencoded

How to do a post request using FORM-DATA or x-www-form-urlencoded with Android?

CORS issue when trying to do JQuery post with json data, but not with plain text or x-www-form-urlencoded

Jersey client Post Request with x-www-form-urlencoded Fails

Spring - wrong encoding POST request with x-www-form-urlencoded

Post a x-www-form-urlencoded request from React Native

post application/x-www-form-urlencoded Alamofire

Swift 4 send POST request as x-www-form-urlencoded

RestSharp post request - Body with x-www-form-urlencoded values

How to send post request with x-www-form-urlencoded body with loopj-async-http library

how to post data in node.js with content type ='application/x-www-form-urlencoded'

How to escape + in post call content type as application/x-www-form-urlencoded

How to do a x-www-form-urlencoded POST login using cypress?

How to force Angular2 to POST using x-www-form-urlencoded

How do I post data using okhttp library with content type x-www-form-urlencoded?

How to send post request with content-type x-www-form-urlencoded android retrofit

Swift - How to send POST request with "x-www-form-urlencoded" content-type

How to POST with application/x-www-form-urlencoded header and URLSearchParams using isomorphic-fetch

Akka HTTP how to POST singleRequest with Content-Type application/x-www-form-urlencoded

How test Post request with custom object in content type application/x-www-form-urlencoded?