I want to enable CORS on one specific action in an Asp.net Web Api. Here's how I'm trying to do it:
[Route("api/mycontroller/myaction")]
[HttpPost]
[EnableCors("https://example.com", "*", "post")]
public async Task<IHttpActionResult> MyAction()
{
...
}
But when I send an OPTIONS request to the route, I get back an error: "The requested resource does not support http method 'OPTIONS'." I also tried removing the [HttpPost] annotation to no avail. What am I missing?
For me, I added the following headers to the request by adding the following code to the Application_BeginRequest function of the Global.asax.cs file:
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin", StringComparer.CurrentCultureIgnoreCase)
&& Request.HttpMethod == "OPTIONS")
{
Response.AddHeader("Access-Control-Allow-Headers", "content-type", "accept", "pragma", "cache-control", "authorization");
Response.End();
}
}
I have little idea why this works. Out of curiosity, I tried adding all headers by using an asterisk but then Web API complained that the Authorization header was missing.
You've probably missed the higher level call to HttpConfiguration.EnableCors
, as described here: https://enable-cors.org/server_aspnet.html.
Add this code to your configuration:
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
}
To ensure the OPTIONS
request gets handled by your application code and not some other part of the system before it reaches your app code, you may try adding the following to your web.config
:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
You might also need to include:
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS"
modules="IsapiModule" requireAccess="None"
scriptProcessor="C:\Windows\System32\inetsrv\asp.dll"
resourceType="Unspecified" />
See the answer at IIS hijacks CORS Preflight OPTIONS request.
Or maybe even just this:
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS"
modules="ProtocolSupportModule" requireAccess="None" />
If none of that on its own works, then in your global.asax
or other code you might try:
if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
{
filterContext.HttpContext.Response.Flush();
}
…or some other variation on that, for example:
if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OridinalIgnoreCase)
&& Request.HttpMethod == "OPTIONS") {
Response.Flush();
}
Regardless of what specific code you use to do it, the point is to:
OPTIONS
requests are actually getting caught/handled by your application code—not caught/handled by some other part of the system before ever reaching your app codeOPTIONS
requests in your application codeOPTIONS
handling in your application code just do Response.Flush()
Or another approach I’m not sure is relevant to your situation as coded but I’ll mention just in case:
public HttpResponseMessage Options()
{
var response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK
};
return response;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With