修改URI格式后ASP.NET Core Web API端点抛出HTTP 405错误
结合你描述的部署场景和错误日志,以下是最可能的问题点及对应的解决方法:
核心问题分析
ASP.NET Core未识别子路径基址
你的API部署在/webApi1这类子路径下,但ASP.NET Core默认以根路径(/)作为路由解析的基准,导致实际请求的/webApi1/api/v1/FetchData被路由系统错误解析,无法匹配到定义的api/v{version}/[controller]/[action]路由规则,最终触发405错误(找不到对应POST方法的有效端点)。IIS模块拦截干扰
日志中的sc-win32-status=1(ERROR_INVALID_FUNCTION)通常和IIS模块处理顺序有关,比如WebDAV模块会默认拦截POST请求,或者静态文件模块优先处理了本该由ASP.NET Core管道接收的请求。
解决步骤
1. 配置API的路径基址
给每个Web API添加子路径基址配置,让应用知道自己部署在/webApi1、/webApi2这类子路径下:
在每个API项目的Program.cs中添加:
var builder = WebApplication.CreateBuilder(args); // 读取配置或手动指定当前API的子路径 var pathBase = "/webApi1"; // 对应webApi2、webApi3需修改为各自的子路径 builder.WebHost.UsePathBase(pathBase); // 其他服务注册代码... var app = builder.Build(); // 应用路径基址到请求管道 app.UsePathBase(pathBase); // 其他中间件配置(如路由、认证等)... app.Run();
更灵活的方式是从appsettings.json读取路径配置:
{ "PathBase": "/webApi1" }
var pathBase = builder.Configuration["PathBase"]; if (!string.IsNullOrEmpty(pathBase)) { builder.WebHost.UsePathBase(pathBase); app.UsePathBase(pathBase); }
2. 禁用IIS WebDAV模块
WebDAV模块会拦截POST请求,在每个API的web.config中添加配置禁用它:
<configuration> <system.webServer> <modules> <remove name="WebDAVModule" /> </modules> <handlers> <remove name="WebDAV" /> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\YourApi.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" /> </system.webServer> </configuration>
3. 验证应用池配置
确保每个Web API对应的IIS应用池配置正确:
- 将应用池的**.NET CLR版本**设置为
无托管代码(ASP.NET Core不需要IIS托管代码) - 应用池身份拥有对应API文件夹的读写权限
4. 调试路由匹配
可以在API的请求管道中添加日志,确认请求路径是否被正确解析:
app.Use(async (context, next) => { var logger = context.RequestServices.GetRequiredService<ILogger<Program>>(); logger.LogInformation("请求路径: {Path}", context.Request.Path); logger.LogInformation("路径基址: {PathBase}", context.Request.PathBase); await next(); });
如果日志显示Path为/api/v1/FetchData且PathBase为/webApi1,说明路径基址配置生效;如果Path是/webApi1/api/v1/FetchData且PathBase为空,说明路径基址未正确配置,需要检查代码。
内容的提问来源于stack exchange,提问作者CodeTruthSeeker

