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

ASP.NET Core中DELETE路由处理器无法工作问题排查

ASP.NET Core REST API DELETE请求405错误排查与解决

问题描述

我正在学习用ASP.NET Core构建REST API,GET和POST请求都能正常运行,但DELETE请求始终报错,收到405 Method Not Allowed响应,响应头显示允许的方法只有GET和POST。

我的DELETE路由配置:

app.MapDelete("/todo/{id}", Results<Ok, NotFound> ([FromRoute] int id, [FromServices] TodoDb db) =>
{
    var result = db.todos.Where<TodoModel>(model => model.id == id).First();

    if (result is null)
    {
        return TypedResults.NotFound();
    }

    db.todos.Remove(result);
    db.SaveChanges();

    return TypedResults.Ok();
});

请求URL:

http://localhost:5168/todo?id=2

收到的响应:

HTTP/1.1 405 Method Not Allowed
Content-Length: 0
Connection: close
Date: Fri, 13 Dec 2024 04:46:32 GMT
Server: Kestrel
Allow: GET, POST

核心原因:路由不匹配

你配置的DELETE路由是路由参数模式:/todo/{id},但实际请求用的是查询参数格式:/todo?id=2。

ASP.NET Core的路由系统会严格匹配端点模板,当你发送DELETE请求到/todo?id=2时,系统找不到对应的DELETE端点(只有/todo的GET、POST端点存在),因此返回405错误。

修复方案(二选一)

  1. 修改请求URL(推荐,符合REST规范)
    使用路由参数格式发送请求:

    DELETE http://localhost:5168/todo/2
    
  2. 修改路由模板(不推荐,不符合REST设计原则)
    将DELETE路由改为查询参数模式:

    app.MapDelete("/todo", Results<Ok, NotFound> ([FromQuery] int id, [FromServices] TodoDb db) =>
    {
        // 原有逻辑保持不变
    });
    

代码中的其他潜在问题优化

除了路由不匹配,你的代码还有几个可优化的点:

1. 避免First()引发异常

当找不到对应ID的Todo时,db.todos.Where(model => model.id == id).First()会直接抛出InvalidOperationException,后续的if (result is null)判断永远不会执行。应改用FirstOrDefault():

var result = db.todos.FirstOrDefault(model => model.id == id);

2. 删除冗余中间件

这段中间件没有任何实际功能,建议删除:

app.Use((context, next) => next(context));

3. 优化GET列表的判断逻辑

db.todos.ToList()永远不会返回null,只会返回空列表,因此result is null的判断可以简化:

app.MapGet("/todo", Results<Ok<List<TodoModel>>, NotFound> ([FromServices] TodoDb db) =>
{
    List<TodoModel> result = db.todos.ToList();
    return result.Any() ? TypedResults.Ok(result) : TypedResults.NotFound();
});

4. 删除无用的转换运算符

TodoModel中的public static implicit operator List<object>(TodoModel v)方法未被使用,且会抛出异常,建议删除。


修复后的DELETE端点代码

app.MapDelete("/todo/{id}", Results<Ok, NotFound> ([FromRoute] int id, [FromServices] TodoDb db) =>
{
    var result = db.todos.FirstOrDefault(model => model.id == id);
 
    if (result is null)
    {
        return TypedResults.NotFound();
    }

    db.todos.Remove(result);
    db.SaveChanges();

    return TypedResults.Ok();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:48:11