Enable CORS
If you read the Web API tutorials from docs.microsoft.com, all of them are teaching you to create the server app (Web API) and the client app (ASp.NET MVC) in the same solution. In fact, we usually separate the server and client application into separate applications. You will then find out the client application cannot call any Web API method in server application. It is because of the CORS.
Cross Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the same-origin policy. Using CORS, a server can explicitly allow some cross-origin requests while rejecting others. CORS is safer and more flexible than earlier techniques such as JSONP. This tutorial shows how to enable CORS in your Web API application.
If you application is ASP.NET Web API 2, now you could do the following to enable CORS
-
install Microsoft.AspNet.WebApi.Cors from Nuget
-
Open file App_Start/WebApiConfig.cs. In Register method, add this code config.EnableCors();
-
You can then adding “[EnableCors(origins: “https://localhost:8080”, headers: “*”, methods: “*”)]” to any method that you want to enable CORS
-
You could also add the following into Web.config, so that CORS will be enabled to all methods
<httpProtocol>
<customHeaders>
<!-- Allow Web API to be called from a different domain. -->
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
</customHeaders>
</httpProtocol>
Now your server application Web API is ready to serve other client applications’ calling. You could read more here, Enabling Cross-Origin Requests in ASP.NET Web API 2
Support HTTP Method ‘OPTIONS’
If your client code is calling the Web API in javaScript, the execution will be fine on Http GET and POST. If your javaScript is Http PUT or DELETE, you will find this error,
The requested resource does not support http method ‘OPTIONS’.
Most of the browser will send a Preflight Request before it sends the actual request. One of the conditions to skip the Preflight Request is “The request method is GET, HEAD, or POST”. if you search to solve it, you will find that most of the result are stating that you could add and remove some handler in web.config could help.
Someone reported that it really solve the problem, but it does not work in my environment. I then also found out that there is another work around and it really works for me. (This is also the main reason why I blog it down and share with you now.) We now adding some handling to the HTTP OPTIONS verb in BeginRequest method.
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
BINGO!
If you check in Fiddler, now the Server Application Web API is accepting the OPTIONS method and response to your client app that the is now ready to receive your PUT/DELETE call.
thank you, it was very helpful
Thanks man, your post save a lot of time to my team.
That’s the issue (the Preflight request) we are having now. Even we are only doing a get request.
However, we don’t have control of the code. Do you think there’s any solution to the OPTIONS verb problem without using the workaround?
Hi Tim,
Are you hosting it on Azure App Service? Without the source code and hosting in Azure App Service, you could enable it in Azure Portal. Steps are,
1) Go to the Azure Portal. Click the app service that you want to enable.
2) Under API section, there is one “CORS” menu
3) enter which source URL(s) that you want to allow the JavaScript code running on external host.
4) Click Save
BINGO. It should works now.
We have enabled OPTIONS same way you have explained, but it is causing performance issues because of threadabort exception, site receives around 20 K per min, we have used caching header for pre flight , what is alternative to not call response. End
None of this worked for me. If solution is this difficult on localhost, can’t imagine deploying to 2 different servers.
you are hero !!
Its not working for local host applications (Client http://localhost:4200) as well as webAPI in http://localhost:1234/apiName. I tried all the steps you mentioned
what value did you put to the option to your method? If your client app is on port 4200, and API on port 1234. Then the option of the method should be
“[EnableCors(origins: “https://localhost:4200”, headers: “*”, methods: “*”)]”
I just want to say thank you. I spent days figurine out whats wrong… That last part solve my issue with the Preflight request. I added the Application_BeginRequest on the global.asax and now it work.
Thanks again