0

我想将 asp.net api-versioning 应用到我的网络应用程序(没有版本控制)。然而,棘手的问题是我必须确保 API 可以在有和没有 api-version 的情况下工作。

    [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() {
        
        }
    }


我有一个具有多个操作的控制器,每个操作都定义了一个唯一的路由名称。当我向控制器添加两条路由(有版本和无版本)时,会出现路由名称冲突错误:

具有相同名称“GET Products/GetLatestAsync”的属性路由必须具有相同的模板:

操作:'Service.Controllers.ProductController.GetLatestAsync (ProductFD)' - 模板:'api/products/{productId}/Product'

操作:'Service.Controllers.ProductController.GetLatestAsync (ProductFD)' - 模板:'api/v{version:apiVersion}/products/{productId}/Product'

StackOverflow 上有几个答案说可以通过删除为操作方法定义的路由名称来解决该问题。但是,在我的场景中,路由名称用于在项目的多个位置创建 URL 链接。

有没有一种方法可以解决这个问题?我想知道是否可以将版本附加到路由名称变量或将非版本 api 映射到 version/1.0 ...?另一方面,在极少数情况下,我会更新控制器中的所有方法。那么我是否有可能只在控制器的顶层定义一个路由前缀,而只在方法级别应用 api-version?

4

1 回答 1

0

路由名称和路由表不支持 API 版本。为了使其工作,您需要像您一样使用双重路由注册,因为您是通过 URL 段进行版本控制(不推荐)。如果客户端正确地跟踪服务器返回的链接,那么始终使用其中包含显式版本的路由就可以了。如果客户端不遵守这一点,而只是直接调用 API 而不使用 API 版本,则第二个模板将为您处理。如果您只使用同一个控制器生成链接,那么我建议CreatedAtAction您改用它,因为它不依赖于路由名称。如果我没记错的话,您可以指定每个[Route]优先级的顺序。如果未指定,它将是指定的第一个属性 - 这很重要。

您还需要启用:

services.AddApiVersioning(options => options.AssumeDefaultVersionWhenUnspecified = true);

如果你还没有。

最后但并非最不重要的一点是,请注意已知的重大更改:从控制器操作名称中修剪的异步后缀。这让很多人陷入了困境。

于 2020-09-16T21:42:52.037 回答