Web Api 2 Handle OPTIONS Requests

12,663

Solution 1

Non elegant way to solve this task is adding in each controller manually

[AcceptVerbs("OPTIONS")]
public HttpResponseMessage Options()
{
    var resp = new HttpResponseMessage(HttpStatusCode.OK);
    resp.Headers.Add("Access-Control-Allow-Origin", "*");
    resp.Headers.Add("Access-Control-Allow-Methods", "GET,DELETE");

    return resp;
}

Or override MessageHandlers

 public class OptionsHttpMessageHandler : DelegatingHandler
{
  protected override Task<HttpResponseMessage> SendAsync(
  HttpRequestMessage request, CancellationToken cancellationToken)
  {
    if (request.Method == HttpMethod.Options)
      {
         var apiExplorer = GlobalConfiguration.Configuration.Services.GetApiExplorer();

          var controllerRequested = request.GetRouteData().Values["controller"] as string;              
          var supportedMethods = apiExplorer.ApiDescriptions.Where(d => 
             {  
                var controller = d.ActionDescriptor.ControllerDescriptor.ControllerName;
                return string.Equals(
                    controller, controllerRequested, StringComparison.OrdinalIgnoreCase);
            })
          .Select(d => d.HttpMethod.Method)
          .Distinct();

      if (!supportedMethods.Any())
         return Task.Factory.StartNew(
             () => request.CreateResponse(HttpStatusCode.NotFound));

      return Task.Factory.StartNew(() =>
        {
            var resp = new HttpResponseMessage(HttpStatusCode.OK);
            resp.Headers.Add("Access-Control-Allow-Origin", "*");
            resp.Headers.Add(
                "Access-Control-Allow-Methods", string.Join(",", supportedMethods));

            return resp;
        });
}

return base.SendAsync(request, cancellationToken);

  }
}

and then in config

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

even second option is not perfect though... no native build in support

Solution 2

I had the same issue as you, the so called Preflight request, and I figured out that this might be related to a misconfiguration on the Web.Conf file. Comment out or remove, if present, the line containing the "remove" of the OPTIONSVerbHandler.

<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>
Share:
12,663

Related videos on Youtube

Matjaž
Author by

Matjaž

“Always pass on what you have learned.” - Yoda

Updated on September 14, 2022

Comments

  • Matjaž
    Matjaž over 1 year

    I have Web Api 2 backend hosted on Azure and AngularJs forntend. I understand that some of HTTP request use pre-check with OPTIONS request. My question is how to implement backend that way, that all OPTIONS requests will return 200 if there is some action in controller that will handle following GET/POST/PUT/DELETE/....

  • Rob Sedgwick
    Rob Sedgwick over 6 years
    or inherit from your own base class which contains your public HttpResponseMessage Options() method: public abstract class BaseApiController : ApiController
  • JGCW
    JGCW almost 6 years
    You are a hero!