Question

As part of a solution to implement cross-browser, cross-domain support for an MVC4 web application making ajax calls to an MVC4 web api application, I'm using the XDomainRequest object to provide support for cross-domain ajax calls made by IE < 10 clients.

I'm having trouble with POST operations which include JSON in the request body that I expect to be deserialized on the web api side.

When the call is made from IE < 10 using XDomainRequest, I can't explicitly specify application/json as the content type of the request (because you can't modify the headers when using XDomainRequest), so the JSON isn't getting deserialized into to the type specified in the method signature.

Note that cross-domain GET operations work fine in all browsers, so I have my web api configured properly for CORS, etc.

Consider the following POST operation defined on the web api:

public int Customer(Customer customer) {}

Even when a Customer objected represented as JSON is present in the body of the request, customer is always null when the call is made using XDomainRequest using IE < 10. This happens because the request generated by XDomainRequest is missing the content-type: application/json request header.

Is there a way to handle this on the web api side so that I can force the JSON body to be properly deserialized even when the content type isn't specified in the request?

I've read about model binders but unclear if this is what they are intended for.

Here's my XDomainRequest code for reference (fyi that this is part of a function which uses jQuery.ajax for all browsers except IE < 10):

var xdr = new XDomainRequest();
if (xdr) {
    xdr.open(method, url);
    xdr.onload = function() {
        var result = $.parseJSON(xdr.responseText);
        if (result == null || typeof(result) == 'undefined') {
            result = $.parseJSON(data.firstChild.textContent);
        }
        doneCallback(result);
    };
    xdr.onerror = function() {
        failCallback();
    };
    xdr.onprogress = function() {
    };
    xdr.send(data);
}
Was it helpful?

Solution

you could write a delegating message handler where you set incoming request content' content-type header to be application/json if not already present.

OTHER TIPS

I wrote the following handler based on Kiran's answer:

protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
{
    if (request.Method == HttpMethod.Post && request.Content.Headers.ContentType == null)
    {
        request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    }

    return base.SendAsync(request, cancellationToken);
}

You can't do what Kiran suggests because the XDomainRequest's contentType property is read-only.

http://msdn.microsoft.com/en-us/library/ie/cc288107%28v=vs.85%29.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top