[英]How to get rid of route-name conflicts when ensuring api works both with and without the api-version?
I want to apply asp.net api-versioning to my web app (which didn't have versioning).我想将 asp.net api-versioning 应用到我的 web 应用程序(没有版本控制)。 However, the tricky issue is that I must ensure that APIs should work both with and without the api-version.
然而,棘手的问题是我必须确保 API 可以在有和没有 api 版本的情况下工作。
[ApiVersion("1.0")]
[Route("api/products/{productId}/[controller]")]
[Route("api/v{version:apiVersion}/products/{productId}/[controller]")]
[ValidateModel]
[Produces("application/json")]
public partial class ProductController : ControllerBase {
internal const string GetLatestRoute = "GET Product/GetLatestAsync";
[HttpGet(Name = GetLatestRoute)]
public async Task<IActionResult> GetLatestAsync() {
}
}
I have a controller with multiple actions, each of them is defined with a unique route name.我有一个带有多个动作的控制器,每个动作都定义了一个唯一的路由名称。 When I add two routes (with and without versions) to the controller, there comes a route-name conflict error:
当我向控制器添加两条路由(有和没有版本)时,会出现路由名称冲突错误:
Attribute routes with the same name 'GET Products/GetLatestAsync' must have the same template:
具有相同名称“GET Products/GetLatestAsync”的属性路由必须具有相同的模板:
Action: 'Service.Controllers.ProductController.GetLatestAsync (ProductFD)' - Template: 'api/products/{productId}/Product'
操作:'Service.Controllers.ProductController.GetLatestAsync (ProductFD)' - 模板:'api/products/{productId}/Product'
Action: 'Service.Controllers.ProductController.GetLatestAsync (ProductFD)' - Template: 'api/v{version:apiVersion}/products/{productId}/Product'
操作:'Service.Controllers.ProductController.GetLatestAsync (ProductFD)' - 模板:'api/v{version:apiVersion}/products/{productId}/Product'
There are several answers on StackOverflow that say the issue can be solved by removing the route names defined for the action methods. StackOverflow 上有几个答案说这个问题可以通过删除为操作方法定义的路由名称来解决。 However, in my scenario, the route names are used to create Url Links in several places in the project.
但是,在我的场景中,路由名称用于在项目的多个位置创建 Url 链接。
Is there an approach that I can get rid of the issue?有没有一种方法可以解决这个问题? I'm wondering whether I could append version to the route name variable or mapping the non-version api to the version/1.0 ...?
我想知道我是否可以将版本附加到路由名称变量或将非版本 api 映射到 version/1.0 ...? On the other hand, there is a rare case that I update all the methods in a controller.
另一方面,在极少数情况下我更新了控制器中的所有方法。 So is it possible that I only define a route-prefix on the top-level of the controller and only apply the api-version on the method-level?
那么有没有可能我只在控制器的顶层定义一个路由前缀,而只在方法级别上应用 api-version?
Route names and the route table are not API version aware .路由名称和路由表不支持API 版本。 In order for this to work, you need to use double route registration like you have because you are versioning by URL segment (not recommended).
为了使其工作,您需要像您一样使用双路由注册,因为您是按 URL 段进行版本控制(不推荐)。 If clients are properly following the links returned by the server, then always using the route generated with the explicit version in it will do.
如果客户端正确跟踪服务器返回的链接,则始终使用其中包含显式版本的路由即可。 If the client doesn't honor that and just calls the APIs directly without the API version, the second template will handle that for you.
如果客户端不遵守这一点,而只是在没有 API 版本的情况下直接调用 API,则第二个模板将为您处理。 If you are only generating links with the same controller, then I would suggest using
CreatedAtAction
instead because it will not rely on the route name.如果您只生成具有相同控制器的链接,那么我建议改用
CreatedAtAction
因为它不依赖于路由名称。 If memory serves me correct, you can specify the order of each [Route]
for precedence.如果没记错的话,您可以指定每个
[Route]
的优先顺序。 If unspecified, it will be the first attribute specified - which matters.如果未指定,它将是指定的第一个属性 - 这很重要。
You'll also need to enable:您还需要启用:
services.AddApiVersioning(options => options.AssumeDefaultVersionWhenUnspecified = true);
If you haven't already.如果你还没有。
Last, but not least, beware the known, breaking change: Async suffix trimmed from controller action names .最后但并非最不重要的一点是,要注意已知的重大更改: 从控制器操作名称中删除的 Async 后缀。 This has snared many people.
这让很多人陷入了困境。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.