【问题标题】:Web Api 2 Handle OPTIONS RequestsWeb Api 2 处理 OPTIONS 请求
【发布时间】:2016-07-27 00:35:26
【问题描述】:

我在 Azure 上托管了 Web Api 2 后端和 AngularJs forntend。我了解某些HTTP request 使用OPTIONS request 进行预检查。我的问题是如何以这种方式实现后端,如果控制器中有一些操作将处理 GET/POST/PUT/DELETE/... 之后的操作,那么所有 OPTIONS requests 都将返回 200。

【问题讨论】:

    标签: c# asp.net azure asp.net-web-api azure-web-app-service


    【解决方案1】:

    我遇到了与您相同的问题,即所谓的 Preflight 请求,我发现这可能与 Web.Conf 文件的错误配置有关。 注释掉或删除(如果存在)包含 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>
    

    【讨论】:

    • 你是英雄!
    【解决方案2】:

    解决此任务的非优雅方法是手动添加每个控制器

    [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;
    }
    

    或者覆盖 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);
    
      }
    }
    

    然后在配置中

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

    即使是第二个选项也不是完美的...没有本地构建支持

    【讨论】:

    • 或从您自己的基类继承,其中包含您的公共 HttpResponseMessage Options() 方法:公共抽象类 BaseApiController : ApiController
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 2017-10-15
    • 2010-09-18
    • 2016-09-22
    • 2019-09-17
    • 1970-01-01
    相关资源
    最近更新 更多