Web Api 2处理选项请求

时间:2016-04-06 14:21:50

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

我在Azure和AngularJs forntend上托管了HTTP request后端。我了解有些OPTIONS request使用预先核对OPTIONS requests。我的问题是如何以这种方式实现后端,如果控制器中有一些将处理后续GET/POST/PUT/DELETE/...的操作,则所有<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> <style> p{ height: 600px; width: 600px; font-size:17px; } </style> </head> <body> <div ng-app="myApp" ng-controller="editor"> <label for="kys_font_size"> font size:</label> <select ng-model="kys_selected_font" id="fontsize" name="kys_font_size" ng-options="page for page in FontSize(1, 150)" ng-change="changeFont()"> </select> <p contenteditable="true" id="content" ng-change="print()" > </p> <input type="text" ng-model="name1"> <p >{{name1}}</p> </div> <p></p> <script> var app = angular.module('myApp',[]); app.controller('editor',function($scope){ $scope.name1="jpos" $scope.kys_selected_font = "hi there"; $scope.fonttext="hello"; $scope.FontSize = function(start, end) { var size = []; for (var i = start; i <= end; i++) { size.push(i); } return size; }; $scope.print= function(){ }; $scope.changeFont = function(){ $("#content").append("<b size='3' '> This is some text </b>"); $("#one").focus(); }; }); </script> </body> </html> 将返回200。

2 个答案:

答案 0 :(得分:12)

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

[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());

即便是第二种选择并不完美但是......没有本地支持

答案 1 :(得分:5)

我遇到了与您相同的问题,即所谓的Preflight请求,我发现这可能与Web.Conf文件上的错误配置有关。 注释掉或删除包含OPTIONSVerbHandler“删除”的行(如果存在)。

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var env = hostingContext.HostingEnvironment;

    var sharedFolder = Path.Combine(env.ContentRootPath, "..", "Shared");

    config
        .AddJsonFile(Path.Combine(sharedFolder, "SharedSettings.json"), optional: true) // When running using dotnet run
        .AddJsonFile("SharedSettings.json", optional: true) // When app is published
        .AddJsonFile("appsettings.json", optional: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    config.AddEnvironmentVariables();
})