IIS Express中缺少Access-Control-Allow-Methods头致PUT请求CORS失败
本地不同端口的Web应用访问ASP.NET Core 3.1 Web API(IIS Express调试模式),GET、POST请求正常,但PUT请求始终失败。浏览器报错:
Access to ... from origin ... has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
查看浏览器请求详情,预检请求和实际PUT请求均执行失败,且预检响应头仅包含:
access-control-allow-headers: * access-control-allow-origin: *
始终缺失access-control-allow-methods头,导致PUT请求无法通过CORS校验。
已尝试的方案
ASP.NET Core内置CORS配置
- 安装
Microsoft.AspNetCore.Mvc.Cors包后,在Startup.cs中添加默认策略:
并在services.AddCors(options => { options.AddDefaultPolicy( policy => { policy.WithOrigins("http://localhost:8080").AllowAnyMethod().AllowAnyHeader(); }); });Configure方法中按要求将app.UseCors()放在Routing之后、Authorization之前。 - 也尝试过全局宽松配置:
services.AddCors();app.UseCors(x => x .AllowAnyMethod() .AllowAnyHeader() .SetIsOriginAllowed(origin => true) .AllowCredentials());
两种配置均无效果,响应头仍缺失目标字段。
- 安装
IIS Express配置文件修改
在所有可能的applicationhost.config路径(包括用户目录、程序安装目录下的配置文件)添加CORS自定义头:<httpProtocol> <customHeaders> <clear /> <add name="access-control-allow-origin" value="*" /> <add name="access-control-allow-headers" value="*" /> <add name="access-control-allow-methods" value="GET,POST,PUT,PATCH,DELETE,OPTIONS" /> </customHeaders> <redirectHeaders> <clear /> </redirectHeaders> </httpProtocol>修改后重启电脑,无任何变化。
Web应用web.config配置
在项目的web.config中添加CORS头配置:<system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="http://localhost:8080" /> <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE" /> <add name="Access-Control-Allow-Headers" value="*" /> </customHeaders> </httpProtocol> </system.webServer>结果依旧无效。
疑问
为何三种配置方式都无法添加access-control-allow-methods头?如何判断预检请求是由IIS还是ASP.NET Core处理?
1. 确保OPTIONS预检请求传递到ASP.NET Core
IIS Express默认可能拦截OPTIONS或PUT请求(尤其是WebDAV模块),导致ASP.NET Core的CORS中间件无法处理。在项目的web.config中添加以下配置,移除干扰模块并放行请求:
<system.webServer> <modules> <remove name="WebDAVModule" /> </modules> <handlers> <remove name="WebDAV" /> <remove name="OPTIONSVerbHandler" /> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> </system.webServer>
2. 严格检查中间件顺序
在Startup.cs的Configure方法中,UseCors必须放在UseAuthorization之前,且位于UseRouting之后、UseEndpoints之前,确保CORS中间件能优先处理请求:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 其他调试/异常处理中间件 app.UseRouting(); // CORS中间件必须在此位置 app.UseCors(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
3. 局部启用CORS策略
如果全局配置不生效,直接在控制器或PUT Action上标记[EnableCors]特性:
[EnableCors("DefaultPolicy")] [ApiController] [Route("api/[controller]")] public class DemoController : ControllerBase { [HttpPut("{id}")] public IActionResult Update(int id, [FromBody] DemoModel model) { // 业务逻辑 return Ok(); } }
4. 判断预检请求处理方的方法
- 添加请求日志:在
Startup.cs中插入自定义中间件,打印请求信息,确认OPTIONS请求是否到达ASP.NET Core:
如果控制台能看到OPTIONS请求日志,说明请求已到达ASP.NET Core;否则是被IIS拦截。app.Use(async (context, next) => { Console.WriteLine($"Received request: {context.Request.Method} {context.Request.Path}"); await next(); }); - 查看响应头标识:如果响应头包含
Server: Microsoft-IIS/10.0且无X-Powered-By: ASP.NET,说明请求由IIS直接处理;若存在X-Powered-By: ASP.NET,则是ASP.NET Core处理了请求。
5. 清理配置冲突
同时配置ASP.NET Core CORS、IIS自定义头、web.config头容易导致冲突。建议先清空所有IIS和web.config的CORS配置,仅保留ASP.NET Core的CORS配置再测试——ASP.NET Core的CORS中间件会自动处理预检请求并生成正确的响应头,无需额外配置IIS层面的头。
内容的提问来源于stack exchange,提问作者nepdev

