How to solve ASP.NET Web API CORS Preflight issue when using PUT and DELETE requests with multiple origins?
I was able to solve my problem by further customizing the Application_BeginRequest method in Global.asax.cs, like this:
protected void Application_BeginRequest(){ if (Request.HttpMethod == "OPTIONS") { Response.StatusCode = (int)HttpStatusCode.OK; Response.AppendHeader("Access-Control-Allow-Origin", Request.Headers.GetValues("Origin")[0]); Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); Response.AppendHeader("Access-Control-Allow-Credentials", "true"); Response.End(); }}
What this code does is add the missing headers to the OPTIONS response (preflight request) that were causing the preflight error. Since I have different origins calling my web API, I'm using Request.Headers.GetValues("Origin")[0])
to set the origin in the response dinamically.
In the WebApiConfig.cs I still specified the different origins but used wildcards on the headers and methods, as well as setting the SupportsCredentials
to true, like this:
var cors = new EnableCorsAttribute("http://localhost:63342,http://localhost:63347,http://localhost:63345", "*", "*");cors.SupportsCredentials = true;config.EnableCors(cors);
Also, if you're using AngularJS like I am, you must configure $http to use credentials. This can be configured globally like this:
angular.module('Application').config(['$httpProvider', function config($httpProvider) { $httpProvider.defaults.withCredentials = true; }]);
And that's it. This solved my problem. If someone else is still having problems, I recommend reading the following publications, which helped me reach my answer:
- http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
- https://evolpin.wordpress.com/2012/10/12/the-cors/
- AngularJS $http, CORS and http authentication
- AngularJS performs an OPTIONS HTTP request for a cross-origin resource
- AngularJS POST Fails: Response for preflight has invalid HTTP status code 404
Create custom attribute using ICorsPolicyProvider
something like following to check if the requested origin is allowed or not
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,AllowMultiple = false)] public class EnableCorsForAPIKeysAttribute : Attribute, ICorsPolicyProvider, IFilter { public async Task<CorsPolicy> GetCorsPolicyAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var corsRequestContext = request.GetCorsRequestContext(); var originRequested = corsRequestContext.Origin; if (await IsValidOrigin(originRequested)) //Check if requested origin is valid or not { // Grant CORS request var policy = new CorsPolicy { AllowAnyHeader = true, AllowAnyMethod = true }; policy.Origins.Add(originRequested); return policy; } else { // Reject CORS request return null; } } public bool AllowMultiple { get {return false;} } }
To use it, add it to your API controller
[EnableCorsForAPIKeys]public class APIBaseController : ApiController{}