3

Thanks for looking!

Background

I am writing an API layer for a company that will be used by disparate apps and external consumers.

On the consumption end, most consumers will call a service via ajax using a jQuery $.post(); however, Internet Explorer makes our lives more challenging (of course!). For IE, I must use the XDomainRequest object because IE will not run a jQuery $.post() and because if I use IE's XMLHttpRequest(), I get a security message which is unacceptable (again--of course!):

enter image description here

Otherwise, XMLHttpRequest() works fine.

I am using C#, .NET MVC 4 (WebApi)

Problem

The problem is that XDomainRequest does not allow you to set the Content-Type header and always defaults to text-plain which MVC 4 WebApi controllers will not accept (and yet again--of course!!).

Question

How can I intercept requests for my controllers, detect the presence of text-plain content types and change them to text-json content-type on the fly?

Thanks in advance!

Community
  • 1
  • 1
Matt Cashatt
  • 23,490
  • 28
  • 78
  • 111
  • "because IE will not run a jQuery $.post()" You sure about that? – BFree Jan 16 '13 at 19:16
  • I am using IE 8 and it doesn't seem to be doing it, probably because it is cross-domain. Let me check again. . . – Matt Cashatt Jan 16 '13 at 19:19
  • 1
    After looking around a bit, try adding a cache busting parameter at the end of the post url: e.g. $.post("my/url?d=" + new Date().getMilliseconds().....) – BFree Jan 16 '13 at 19:25
  • @BFree--Yup. In IE8, I can put a breakpoint right on `$.post()` and it will be hit, but the callback function is never executed. It's as if IE just steps over the `.post()`. The same `.post()` code runs fine in other browsers. – Matt Cashatt Jan 16 '13 at 19:26
  • @Bfree--OK, tried the cacheBuster, but sadly that didn't help. – Matt Cashatt Jan 16 '13 at 19:26
  • That's a problem. I would first try to tackle that before trying to hack the content-type of the request. There are some other suggestions out there for $.post with IE8, try those first. My $0.02. – BFree Jan 16 '13 at 19:30
  • I agree with @BFree that this is probably a client issue. However, for the workaround you want `DelegatingHandler` which you can register. This will allow you to add pre and post logic to the asynchronous call. – Davin Tryon Jan 16 '13 at 19:38
  • Check your network traffic with IE developer tools or Fiddler. Make sure the request reaches the server and inspect the response. – jrummell Jan 16 '13 at 20:30
  • When I see cross-domain web service problems I immediately think of JSONP. Looks like Web API might not support it out-of-the-box, but there are options. Worth considering? - http://stackoverflow.com/questions/9421312/jsonp-with-asp-net-web-api – Snixtor Jan 16 '13 at 21:32
  • Are you doing non SSL post? Are you getting same warning even if you using HTTPS url for post? – Akash Kava Apr 26 '13 at 06:33

2 Answers2

4

Well after two days and pouring over documentation and reading in this thread I've been able to make this work. So please forgive me if my description of the solution is poor; this is the first time I answer one of these types of threads. Since it took me so long to find the problem I figured it is worth saving some soul from falling into this same problem.

The source for my help came from the above link by byterot.

  1. First thing I did was to create a DelegatingHandler. So in my helper folder or where every you want to create a class and call it what you want.
    Here is mine:

    public class ContentTypeHandler : DelegatingHandler
    {
        /** Check that this is an IE browser. */
        if ((request.Headers.UserAgent.ToString().IndexOf("MSIE", System.StringComparison.Ordinal) > -1))
        {
            MediaTypeHeaderValue contentTypeValue;
            if (MediaTypeHeaderValue.TryParse("application/json", out contentTypeValue))
            {
                request.Content.Headers.ContentType = contentTypeValue;
                request.Content.Headers.ContentType.CharSet = "utf-8";
            }
        }
    
        /** Return request to flow. */
        return base.SendAsync(request, cancellationToken)
           .ContinueWith(task =>
           {
                // work on the response
                var response = task.Result;
                return response;
           });
    }
    
  2. Last think that you have to do is call the Handler in your Global.asax.cs file inside your Application_Start():

    GlobalConfiguration.Configuration.MessageHandlers.Add(new ContentTypeHandler());
    

That's all I did and it worked. So good luck I hope this helps someone.

Jesse
  • 8,605
  • 7
  • 47
  • 57
3

There is no problem modifying request in HTTP stack. It can be done by writing and registering your custom DelegatingHandler before it gets to the controller. Delegating handler can take care of this early-on in the game, so your request will arrive to the controller in the form you want it to. It could be route-specific handler as well. http://msdn.microsoft.com/en-us/library/system.net.http.delegatinghandler.aspx

Did you try $.ajax instead of $.post ?

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • Yes I have tried every variation of jQuery posts, ajacx, etc. It seems that IE simply does not allow cross-domain ajax posts via jquery. I appreciate the link to the msdn doc on a delegating handler, but if you have example code that would really be great. – Matt Cashatt Jan 16 '13 at 20:31
  • This is great delegating handler source for you http://byterot.blogspot.com/search?q=delegatinghandler – T.S. Jan 16 '13 at 21:56