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

Minimal API中CreatedAtRoute路由匹配异常问题排查

问题描述

我正在创建一个Minimal Web API,定义了以下两个路由:

app.MapGet("/reports/{id:Guid}", GetReportById);
app.MapPost("/reports", CreateReport);

对应的委托处理方法如下:

public static async Task<Results<Ok<ActivityReport>, NotFound, BadRequest<string>>> GetReportById(
    [AsParameters] ActivityReportingServices services,
    Guid id)
{
    if (id == Guid.Empty)
    {
        return TypedResults.BadRequest("Id is not valid.");
    }

    var activityReport = await services.Context.ActivityReports.SingleOrDefaultAsync(report => report.Id == id);

    if (activityReport == null)
    {
        return TypedResults.NotFound();
    }

    return TypedResults.Ok(activityReport);
}

以及:

public static async Task<CreatedAtRoute<ActivityReport>> CreateReport(
    [AsParameters] ActivityReportingServices services,
    ActivityReportForCreateDTO activityReport)
{
        
    var report = new ActivityReport() { Clients = activityReport.Clients };

    services.Context.ActivityReports.Add(report);
    await services.Context.SaveChangesAsync();

      
    return TypedResults.CreatedAtRoute(report, "/reports/{report.Id}");
}

ActivityReport类的Id成员为Guid类型。我的问题是,当CreateReport方法尝试返回TypedResults.CreatedAtRoute(report, $"/reports/{report.Id}")时,会抛出异常:“System.InvalidOperationException: No route matches the supplied values”。我曾尝试将路由"/reports/{id:Guid}"改为"/reports/{id}",并将GetReportById中的Id参数改为string类型,但问题仍未解决。请问我哪里操作错误?


问题原因与解决方案

你误用了CreatedAtRoute的参数格式。这个方法的第二个参数不是直接传URL路径,而是路由名称或者路由参数的键值对,用来匹配已定义的路由模板。

正确的两种实现方式:

  1. 命名路由+参数键值对
    先给MapGet的路由设置一个名称,比如:

    app.MapGet("/reports/{id:Guid}", GetReportById).WithName("GetReportById");
    

    然后在CreateReport中,通过路由名称和参数匹配:

    return TypedResults.CreatedAtRoute(report, new { id = report.Id });
    

    这里的匿名对象new { id = report.Id }要和路由模板中的参数名{id:Guid}完全对应,ASP.NET会自动根据路由名称和参数生成正确的URL。

  2. 直接使用路由模板匹配(不命名路由)
    如果不想给路由命名,也可以直接传入参数键值对,框架会自动匹配对应的路由模板:

    return TypedResults.CreatedAtRoute(report, new { id = report.Id });
    

    注意:此时匿名对象的参数名必须和目标路由的参数名(id)一致,类型也要匹配(Guid)。

你之前的错误点:

  • 直接把拼接好的URL字符串传给CreatedAtRoute,但这个方法并不接受完整URL作为参数,而是需要路由标识和参数集合,所以框架无法找到匹配的路由规则,抛出异常。
  • 修改路由模板和参数类型的操作没有解决根本问题,因为核心错误是参数传递方式不对。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 05:40:25