Ajax 带有自定义 header 的请求发送到启用了 CORS 的 Web API 服务器

Ajax request with custom header sent to Web API server with CORS enabled

我正在尝试正确设置 Web API 网络服务以使用 CORS,但最近运气不佳。

我有一个来自移动应用程序的 html 页面,使用 ajax 请求获取一些数据:

Webservices.GetUserLevel = function() {
    var userLevel = null;

    $.ajax({
        url: _CONNECTION_STRING + "getuserlevel/" + _USER_PIN,
        contentType:'application/json; charset=utf-8',
        type: 'GET',
        async: false,
        cache: false,
        crossDomain: true,        
        data: {
            BlackberryPin: _USER_PIN
        },
        beforeSend: function(xhr) {
            xhr.setRequestHeader('BlackberryPin', _USER_PIN);                   
        },
        success: function(data) {
            userLevel = data;
        },
        error: function(xhr, ajaxOptions, thrownError) {
            Webservices.HandleError(xhr, ajaxOptions, thrownError);
        }
    });

    return userLevel;
}

我从那个电话中得到的回复是:

XMLHttpRequest 无法加载 http://.. urlGoesHere ../getuserlevel/2B65FA52?BlackberryPin=2B65FA52&_=1427109244103。请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源“http://localhost:3726”。响应具有 HTTP 状态代码 404。

在网络服务上,控制器方法如下所示:

public UserLevel GetUserLevel(string pin)
{    
    return _service.GetUserLevel(pin);
}

我在我的网络服务的 web.config 中启用了 CORS:

<system.webServer>            
<validation validateIntegratedModeConfiguration="false" />
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization, Accept, X-Requested-With, Origin, BlackberryPin" />
    <add name="Access-Control-Allow-Methods" value="OPTIONS, TRACE, GET, HEAD, POST, PUT" />
  </customHeaders>

</httpProtocol>
<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>

我们的网站 api 配置相当简单:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.Filters.Add(new HandleExceptionAttribute());
        config.Filters.Add(new WebAuthorisationFilter());            
    }
}

我们设置了一个网络授权过滤器来检查自定义 header 'BlackberryPin' 并将拒绝不包含 header 和有效 pint。在使用远程调试器测试 web 服务时,我发现它没有获取授权过滤器代码,所以我怀疑这里的 routing/CORS 配置有问题。

感谢您提供的任何帮助或想法。

更新:

我还在控制器方法上尝试了以下数据注释:

    [Route("api/erouter/GetUserLevel/{pin}")]        
    [EnableCors("*", "Accept, Origin, Content-Type, OPTIONS, Pin, BlackberryPin", "GET")]
    public UserLevel GetUserLevel(string pin)
    {    
        return _service.GetUserLevel(new ERouterRequest(pin,null));
    }

当我使用 fiddler 调用此方法(作为 GET)时,它成功通过。但是,使用 ajax 调用它 returns 在主 GET 调用之前发送的预检 OPTIONS 请求上出现 405 错误。

仔细查看了 Firebug 中 ajax OPTIONS 调用中的请求 headers。

事实证明,我在配置键 Access-Control-Allow-Headers 下的 web.config 中遗漏了一些已接受的 headers。我添加了 headers: Accept, Accept-Encoding, Accept-Language, Cache-Control, Access-Control-Request-Header, Access-Control-Request-Method.