Can't get CORS to work with web api

Topics: ASP.NET Web API
Mar 28, 2013 at 11:11 AM
Hi,

I just upgraded my web api project to the latest nightly build (130328).

I call config.EnableCors() on WebApiConfig and put the EnableCors attribute on my controller.

As per the specification this should allow all origins and headers on my controller.

But this does not work, as the Access-Control-Allow-Origin header is not sent the browser does not allow the cross site call to my service.

Am I missing something here?

Thanks,
Mar 28, 2013 at 3:00 PM
I got it to work with the following hack:

protected void Application_BeginRequest(object sender, EventArgs e)
{
if (Context.Request.Path.Contains("api/") && Context.Request.HttpMethod == "OPTIONS")
{
    Context.Response.AddHeader("Access-Control-Allow-Origin", "*");
    Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST PUT, DELETE, OPTIONS");
    Context.Response.End();
}
}

It seems that the CORS implementation does not respond correctly when the browser sends the OPTIONS method.

Any ideas regarding this?
Mar 28, 2013 at 4:55 PM
Did you check for the common WebDAV issues?

http://brockallen.com/2012/10/18/cors-iis-and-webdav/
Mar 28, 2013 at 5:03 PM
Yes I did.
I just rechecked it and it's like the example on your blog post.

Additionally, I just noticed that my hack does not work on an Azure Web Role.
Mar 28, 2013 at 5:15 PM
This is very strange. Can you share a simple/standalone repro including the javascript client?
Thanks,
Yao
Mar 28, 2013 at 7:22 PM
Sure. :)
I have a repro project ready.

How can I upload it?

Thanks,
Bruno
Mar 28, 2013 at 9:50 PM
Maybe you can upload it to skydrive or dropbox and share the link?
Thanks,
Yao
Mar 28, 2013 at 11:22 PM
Here it is.
https://www.dropbox.com/s/a81pk6izwcegmzb/CorsRepro.zip

Hope it helps.

Thanks,
Bruno
Mar 30, 2013 at 1:28 AM
Hi Bruno,
Looks like the issue is caused by the usage of attribute routing where the following will produce a single route entry that only allows HTTP GET to come through. Requests with any other HTTP methods would not even reach the Web API pipeline.
    [RoutePrefix("api/profiles")]
    public class ProfilesController : ApiController
    {
        [System.Web.Http.HttpGet("{personId}/app/{appId}", RouteName = "ProfileApiGetPersonApp")]
        public async Task<HttpResponseMessage> GetPersonApplicationProfile(Guid personId, Guid appId)
Just to verify, can you try adding another route for OPTIONS and see whether the request succeeds after that?
    [RoutePrefix("api/profiles")]
    public class ProfilesController : ApiController
    {
        [System.Web.Http.HttpGet("{personId}/app/{appId}", RouteName = "ProfileApiGetPersonApp")]
        [System.Web.Http.HttpOptions("{personId}/app/{appId}", RouteName = "ProfileApiGetPersonApp2")]
        public async Task<HttpResponseMessage> GetPersonApplicationProfile(Guid personId, Guid appId)
Thanks,
Yao
Apr 1, 2013 at 11:33 AM
Hi Yao,

It seems to work when I add the routes for the OPTIONS method. Additionally, I have another controller that does not use attribute routing and it works fine as is. So it seems consistent with your analysis.

Now, my question is: we shouldn't have to do this when using CORS, right?

Anyway thanks a lot for your feedback. :)

Bruno
Apr 1, 2013 at 6:52 PM
You're welcome, Bruno. Regarding your question, yes, we'll look into ways of improving the experience so that this could work seamlessly.

Thanks,
Yao
Oct 23, 2014 at 3:04 PM
Has this been fixed. I'm still having the problem and I can't seem to get any of the above solutions to work. I didn't quite understand the statement, "usage of attribute routing where the following will produce a single route entry that only allows HTTP GET" means or how to fix it.

I've been working on this all week. Today is my 4th day. I could really used a little help or if this bug has been fixed where can I get it?
Coordinator
Oct 23, 2014 at 4:01 PM
The attribute routing issue mentioned above should no longer be relevant.

Could you please tell us more about your setup and the behavior you are seeing? Which browser? Are you hosting in IIS or in your own process? Have you traced the wire to see what is happening with the request?