Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP Web API POST request with CORS and IE9 (XDomainRequest object)

I've been going crazy here trying to get jquery.ajax to work with ie9. So I have a ASP Web API 2 Rest API that implements CORS. CORS requests from all browsers work. IE9 didnt work since it uses the XDomainRequest. I managed to get it too work by making a custom implementation of ajaxTransport for IE9.

Right now GET requests seem to work fine. But when I do a post request from IE9 I get a HTTP error 415 - unsuportted media type.

I've set the content-type to:"application/json" and I've also tried "application/x-www-form-urlencoded", but from what I understood XDomainRequest doesnt support everything with custom headers? Does anybody know if something specific needs to be setup on the WebAPI or do I need to tweak the request?

My request looks like this:

                        $.ajax({
                        url: hostname + "/api/DDC/Book",
                        type: "POST",

                        contentType: "application/json",
                        data: {
                            DealID: function () {
                                return viewModel.get("DealID");
                            },
                            LocationID: function () {
                                return viewModel.get("LocationID");
                            },
                            Time: function () {
                                return viewModel.get("selectedDateTime.Time");
                            }

                        }
                    })

On the server I have this:

[HttpPost("DDC/Book")]
    [EnableCors(origins: "*", headers: "*", methods: "POST, GET, OPTIONS, PUT, DELETE")]
    public dynamic Post(BookModel model)
    {
       .........

When I analyze the failed request in the IE debugger this are the request headers that get sent out:

Key Value
Request POST //api/DDC/Book HTTP/1.1
Accept  */*
Origin  http://myurl.com
Accept-Language hr-HR
Accept-Encoding gzip, deflate
User-Agent  Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host    www.somehost.com
Content-Length  55
DNT 1
Connection  Keep-Alive
Cache-Control   no-cache

I'm really losing all hope here and IE is making my go crazy (damn you Microsoft :D ), so any help or advice is much appriciated.

EDIT: From more reasearch I found out that WebAPI requires a content-type to work and XDomainRequest doesnt send out one. So the only solution I see is too tweak my webapi to have a default content-type when nothing is set. Don't know how to this yet though

EDIT2: Hacked my way through temporarily by transforming all my POSTs, to GETs, dont know how smart is this, but I see no bigger problem with it now, so it will do until I fix the problem

like image 679
Dennis Puzak Avatar asked Dec 26 '22 20:12

Dennis Puzak


1 Answers

Managed to solve it myself. As pointed by Ray Nicholus when there is no Content-Type ASP Web API defaults to an "application/octet-stream" Content-Type. I need a default of "application/x-www-form-urlencoded".

I managed to achive this by writing my own simple message handler that checks an incoming requests "Content-Type" and if nothing is present it adds an "application/x-www-form-urlencoded" one.

This is the code:

public class DefaultContentTypeMessageHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Content.Headers.ContentType == null)
            request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");


        var response = await base.SendAsync(request, cancellationToken);


        return response;
    }

}

UPDATE:

As written by Robert Christ in the comment below I am extending the answer a bit for those who have not worked with message handlers before:

For those who don't understand at first glance, DelegatingHandlers allow you to modify requests / response objects before they really hit the WebAPI framework internals. Nothing else in the framework really lets you modify the incoming request before model binding, without actually writing custom model binders (eugh). so instead, here, you can sniff out a null content type (which is guaranteed by shortcomings in the XDomainRequest spec), update it to xml or json, and you will be able to parse the incoming request correctly.

After you have written a message handler you need to register it with WebAPI. You do that in the WebApiConfig class:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {

        config.MessageHandlers.Add(new DefaultContentTypeMessageHandler());
        // Rest of your code

     }
 }
like image 125
Dennis Puzak Avatar answered Jan 23 '23 08:01

Dennis Puzak