Api .net core 3.0 中的路由

Api Routing in .net core 3.0

我是 .net core 的新手,我想为我的 api 设置一个 MapRoute。 我在 startup.cs 中配置端点,如

app.UseEndPoints(endpoints=>{
    endpoints.MapController("defaultApi","v1/{controller="cont"}/{action}/{id?}");
    endpoints.MapController("defaultNonActionApi","v1/{controller="cont"}/{id?}")l
    endpoints.MapHealthChecks("/healthz");
});

并在 controller.cs

[ApiController]
[Route("[controller]")]
public class contController:ControllerBase{
    [HttpGet]
    public ActionResult Get(){}
}

useEndpoints 中的配置没有用,如果我转到 https://localhost:port/v1/cont it return a 404 and if i goto https://localhost:port/cont 它可以 return 一个预期的结果。

RouteAttribute 似乎覆盖了 useEndpoints 中的配置,但我无法删除 ApiController 的 RouteAttribute。

我知道将 Route("[controller]") 更改为 Route("v1/[controller]") 可以解决这个问题,但我想要的是可以在 startup.cs 中配置的更全局的东西。 谢谢。

下面是一个简单的演示:

1.Create 自定义 MvcOptionsExtensions:

public static class MvcOptionsExtensions
{
    public static void UseGeneralRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
    {
        opts.Conventions.Add(new RoutePrefixConvention(routeAttribute));
    }

    public static void UseGeneralRoutePrefix(this MvcOptions opts, string prefix)
    {
        opts.UseGeneralRoutePrefix(new RouteAttribute(prefix));
    }
}

public class RoutePrefixConvention : IApplicationModelConvention
{
    private readonly AttributeRouteModel _routePrefix;

    public RoutePrefixConvention(IRouteTemplateProvider route)
    {
        _routePrefix = new AttributeRouteModel(route);
    }

    public void Apply(ApplicationModel application)
    {
        foreach (var selector in application.Controllers.SelectMany(c => c.Selectors))
        {
            if (selector.AttributeRouteModel != null)
            {
                selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_routePrefix, selector.AttributeRouteModel);
            }
            else
            {
                selector.AttributeRouteModel = _routePrefix;
            }
        }
    }
}

2.Register 在 Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(o => { o.UseGeneralRoutePrefix("v1"); });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

3.Controller:

[ApiController]
[Route("[controller]")]
public class contController:ControllerBase{
    [HttpGet]
    public ActionResult Get(){}
}