You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET Core 2.1迁移3.1后路由AmbiguousMatchException问题

解决.NET Core 3.1 API版本路由冲突的AmbiguousMatchException问题

这个问题我之前迁移项目时也碰到过,核心原因是.NET Core 3.0+引入的端点路由系统和旧版MVC路由的处理逻辑不一样,API版本的路由约束需要额外配置才能被端点路由正确识别。下面是具体的解决步骤:

一、修正Startup中的服务配置

首先确保ConfigureServices里的API版本配置和控制器服务正确绑定,关键是要明确指定API版本的读取方式,并启用API行为兼容:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Versioning;

public void ConfigureServices(IServiceCollection services)
{
    // 注册控制器服务(.NET Core 3.x推荐用AddControllers替代AddMvc)
    services.AddControllers();

    services.AddApiVersioning(o =>
    {
        o.ReportApiVersions = true;
        o.DefaultApiVersion = new ApiVersion(1, 0);
        o.AssumeDefaultVersionWhenUnspecified = true;
        // 明确指定从URL段读取API版本,这是端点路由识别版本的关键
        o.ApiVersionReader = new UrlSegmentApiVersionReader();
        // 启用API行为,确保和端点路由兼容
        o.UseApiBehavior = true;
    });
}

二、确认中间件顺序和端点映射

Configure方法中,必须保证中间件的顺序正确,端点路由相关的中间件要按UseRoutingUseEndpoints的顺序放置:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    // 必须在UseEndpoints之前调用UseRouting
    app.UseRouting();

    // 如果有认证/授权中间件,要放在UseRouting之后、UseEndpoints之前
    // app.UseAuthorization();

    // 映射控制器端点,这一步不能少
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

三、检查控制器的特性标记

确保每个版本的控制器都正确标记了API版本和路由约束,并且添加[ApiController]特性(这个特性会启用API专属的路由行为):

V1控制器示例

[ApiVersion("1.0")]
[Route("v{version:apiVersion}/[controller]")]
[ApiController]
public class SAPClientController : ControllerBase
{
    [HttpGet("GetSap")]
    public IActionResult GetSap()
    {
        return Ok("来自V1的GetSap响应");
    }
}

V2控制器示例

[ApiVersion("2.0")]
[Route("v{version:apiVersion}/[controller]")]
[ApiController]
public class SAPClientV2Controller : ControllerBase
{
    [HttpGet("GetSap")]
    public IActionResult GetSap()
    {
        return Ok("来自V2的GetSap响应");
    }
}

问题根源解释

在.NET Core 2.1的UseMvc路由系统中,API版本的筛选是在MVC的动作选择阶段完成的;而3.x的端点路由是更底层的路由机制,会先匹配所有符合URL模板的端点,再进行动作筛选。如果没有明确配置UrlSegmentApiVersionReader,端点路由无法识别URL中的version参数是API版本约束,就会认为三个控制器的GetSap动作都匹配同一个URL模板,从而抛出AmbiguousMatchException

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

火山引擎 最新活动