You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework4.8中ASP.NET MVC OPTIONS预请求未触发处理问题

问题原因及解决方案

原因分析

  1. IIS默认拦截OPTIONS请求:IIS自带的OPTIONSVerbHandler会自行处理OPTIONS预请求,不会将其转发到ASP.NET请求管道,导致Application_BeginRequest和MVC ActionFilter都无法捕获到这类请求。
  2. MVC ActionFilter的局限性:ActionFilter仅对匹配到控制器Action的请求生效,而OPTIONS预请求通常没有对应的Action路由,因此不会触发OnActionExecuting方法。

解决步骤

1. 修改Web.config,让OPTIONS请求进入ASP.NET管道

在<system.webServer>节点下添加或修改处理器配置,替换默认的OPTIONS处理逻辑:

<system.webServer>
  <handlers>
    <!-- 移除默认的OPTIONS处理器 -->
    <remove name="OPTIONSVerbHandler" />
    <!-- 添加自定义OPTIONS处理器,将请求转发给ASP.NET -->
    <add name="OPTIONSVerbHandler" 
         path="*" 
         verb="OPTIONS" 
         modules="ManagedPipelineHandler" 
         scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" 
         resourceType="Unspecified" 
         requireAccess="None" />
  </handlers>
</system.webServer>

2. 在Global.asax中完整处理CORS逻辑

修改Application_BeginRequest方法,覆盖OPTIONS预请求处理和动态Origin头设置:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var context = HttpContext.Current;
    var request = context.Request;
    var response = context.Response;

    // 处理OPTIONS预请求
    if (request.HttpMethod == "OPTIONS")
    {
        // 设置允许的请求方法(根据实际接口支持的方法调整)
        response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        // 设置允许的请求头(*表示允许所有,也可指定具体头如Content-Type)
        response.Headers.Add("Access-Control-Allow-Headers", "*");
        // 设置预请求结果的缓存时长(单位:秒)
        response.Headers.Add("Access-Control-Max-Age", "86400");
        // 直接返回200状态,终止后续管道执行
        response.StatusCode = 200;
    }

    // 动态设置Access-Control-Allow-Origin
    var needsCustomOrigin = ConfigurationManager.ConnectionStrings["CustomOrigin"]?.ConnectionString ?? "";
    if (!string.IsNullOrWhiteSpace(needsCustomOrigin))
    {
        string originHeader = null;
        // 优先获取Origin头
        if (request.Headers.AllKeys.Contains("Origin"))
        {
            originHeader = request.Headers["Origin"];
        }
        // 无Origin时从Referer提取源域名(需去除路径部分)
        else if (request.Headers.AllKeys.Contains("Referer"))
        {
            try
            {
                var refererUri = new Uri(request.Headers["Referer"]);
                originHeader = $"{refererUri.Scheme}://{refererUri.Host}:{refererUri.Port}";
            }
            catch (UriFormatException)
            {
                // 处理无效Referer的情况
                originHeader = string.Empty;
            }
        }

        if (!string.IsNullOrWhiteSpace(originHeader))
        {
            // 避免重复添加响应头
            if (!response.Headers.AllKeys.Contains("Access-Control-Allow-Origin"))
            {
                response.Headers.Add("Access-Control-Allow-Origin", originHeader);
            }
            // 如果需要支持带凭据的请求(如Cookie),添加以下头
            response.Headers.Add("Access-Control-Allow-Credentials", "true");
        }
    }

    // OPTIONS请求处理完成后直接结束响应
    if (request.HttpMethod == "OPTIONS")
    {
        response.End();
    }
}

3. 移除无效的ActionFilter

由于ActionFilter无法捕获无路由匹配的OPTIONS请求,之前定义的MyActionFilterAttribute可以直接移除,无需再使用。

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:55:14