You need to enable JavaScript to run this app. ASP.NET Core Web API模板中PUT、DELETE请求报404问题求助
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core Web API模板中PUT、DELETE请求报404问题求助

PUT/DELETE请求返回404的排查与解决步骤

优先排查代码层路由匹配问题(80%的这类问题根源不在IIS配置)

先看你贴的两个Action的写法,本身就存在容易导致路由不匹配的问题:

  • 确认控制器类的全局路由配置:先检查ClientsController类的定义上有没有标注全局路由特性,比如[Route("api/[controller]")]、[ApiController]。如果没有全局路由前缀,你现在Update方法上写的[HttpPut("{id:length(24)}")]生成的匹配路径是没有api/Clients前缀的,实际匹配的是根路径下的24位id,和你发请求用的/api/Clients/xxx路径根本对不上,自然会404。
  • 排查Action上的路由冲突:你写的Delete方法同时叠加了[HttpDelete("{id:length(24)}")]和[Route("api/Clients/{id}")]两个独立的路由特性。特性路由的核心规则是:同一个Action上如果写了多个独立路由模板,会生成多条独立的路由规则——这就导致你现在Delete方法同时匹配两个规则:一个是不带id长度约束、不限制HTTP谓词的api/Clients/{id},另一个是仅匹配DELETE请求、要求id必须为24位长度的路由。路由匹配的时候如果你的请求id长度不对、或者优先级判断出问题,就会直接匹配失败抛404,根本走不到方法内部的client==null判断逻辑。
  • 快速定位路由问题的调试方法:在Program.cs的端点配置里加临时调试接口,遍历所有已注册的路由规则,就能看到你发的请求到底有没有对应的匹配项:
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        // 临时调试接口,访问/route-debug就能列出所有注册的路由
        endpoints.MapGet("/route-debug", async context =>
        {
            var endpointSource = context.RequestServices.GetRequiredService<EndpointDataSource>();
            await context.Response.WriteAsJsonAsync(endpointSource.Endpoints.Select(e => new
            {
                e.DisplayName,
                RoutePattern = (e as RouteEndpoint)?.RoutePattern.RawText,
                HttpMethods = (e as RouteEndpoint)?.Metadata.GetMetadata<HttpMethodMetadata>()?.HttpMethods
            }));
        });
    });
    

IIS层剩余配置排查

你已经试过移除WebDav模块,这部分不用重复操作,重点检查容易漏的配置项:

  • 检查请求过滤规则:打开IIS对应站点的“请求筛选”面板,切到“HTTP谓词” tab,确认PUT、DELETE没有被列在拒绝列表里。很多站点默认的请求过滤规则只允许GET、POST、HEAD请求,未授权的谓词会在IIS层直接返回404,根本不会把请求转发到你的应用。
  • 检查web.config中的处理器配置:确认ASP.NET Core模块(ANCM)的handler配置没有限制HTTP谓词,正确的配置应该是接收所有谓词的请求:
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    
    如果你这里的verb属性写了"GET,POST",那PUT、DELETE请求根本不会被转发到应用,直接被IIS拦截。
  • 确认应用池的管道模式:必须选择集成管道模式,经典管道模式下托管模块不会对非GET/POST的请求做处理,会直接返回404。

现有代码的修正方案

对照你的业务逻辑,修正后的正确写法应该是:

  1. 先给控制器类加全局路由和API控制器特性:
    [Route("api/[controller]")] // 全局路由前缀,自动生成api/Clients路径
    [ApiController]
    public class ClientsController : ControllerBase
    {
        // 原有Update方法逻辑保持不变,路由自动拼接为api/Clients/{id},仅匹配PUT请求、要求id为24位长度
        [HttpPut("{id:length(24)}")]
        public IActionResult Update(string id, Client clientIn)
        {
            var client = _clientService.Get(id);
            if (client == null) return NotFound();
            _clientService.Update(id, clientIn);
            return NoContent();
        }
    
        // 删除原有方法上多余的[Route("api/Clients/{id}")]特性,避免路由冲突
        [HttpDelete("{id:length(24)}")]
        public IActionResult Delete(string id)
        {
            var client = _clientService.Get(id);
            if (client == null) return NotFound();
            _clientService.Remove(client.ClientId);
            return NoContent();
        }
    }
    

兜底验证逻辑

改完配置后如果还是404,用最简单的方法定位故障层:临时把两个Action的HTTP谓词改成POST,比如给Update加[HttpPost("Update/{id:length(24)}")],发POST请求测试:

  • 如果POST请求能正常进入方法、返回预期结果,PUT/DELETE还是404:说明问题出在IIS层的谓词拦截,和代码逻辑无关;
  • 如果POST请求也进不去、还是404:说明问题出在路由模板拼接错误,和HTTP谓词没有关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 16:36:04