随着Web API的不断迭代,为了确保旧版本的客户端能够正常工作,需要在API中添加版本控制功能。在ASP.NET Core中实现版本控制,首先需要在Startup类中配置服务,然后选择一种版本控制策略,比如通过查询字符串、URL或HTTP头部来实现。
在本文中,将探讨如何通过不同的方式在ASP.NET Core中实现API版本控制,并讨论每种方法的优缺点。
在ASP.NET Core的Startup类中配置服务时,可以设置以下属性:
此外,可以使用HttpContext的GetRequestedApiVersion方法获取当前请求的版本,该方法返回ApiVersion类型。
默认的版本号指定方法是通过查询字符串中的api-version参数。例如:
/movies?api-version=2.0
以下是一个通过查询字符串访问不同版本的示例:
[ApiVersion("1.0")]
[Route("movies")]
public class MoviesControllerV1 : Controller
{
[HttpGet]
public IActionResult Get() => Content("Version 1");
}
[ApiVersion("2.0")]
[Route("movies")]
public class MoviesControllerV2 : Controller
{
[HttpGet]
public IActionResult Get() => Content("Version 2");
}
在这个例子中,MoviesControllerV1和MoviesControllerV2分别对应API的1.0和2.0版本。
可以通过路由和apiVersion约束在URL中指定版本号。需要注意的是,如果使用URL指定版本号,查询字符串中的版本号将不再起作用:
[ApiVersion("2.0")]
[Route("actors/v{ver:apiVersion}")]
public class ActorsControllerV2 : Controller
{
[HttpGet]
public IActionResult Get() => Content("Version 2");
}
在这个例子中,ActorsControllerV2的URL中包含了版本号2.0。
要使用HTTP头部传递版本号,首先需要配置版本读取器,告诉中间件如何读取版本。配置完成后,查询字符串中的版本号将不再起作用:
options.ApiVersionReader = new HeaderApiVersionReader("api-version");
在这个例子中,使用了"api-version"作为HTTP头部的键,以保持与查询字符串和URL方法的一致性。
如果不使用[ApiVersion]属性,可以通过Conventions属性配置控制器的版本号:
options.Conventions.Controller()
.HasApiVersion(new ApiVersion(1, 0));
options.Conventions.Controller()
.HasApiVersion(new ApiVersion(2, 0));
在这个例子中,WritersControllerV1和WritersControllerV2分别对应API的1.0和2.0版本,而不需要额外的属性。
还可以使用[MapToApiVersion]属性在控制器内部对操作方法进行版本控制:
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("directors")]
public class DirectorsController : Controller
{
[HttpGet]
public IActionResult Get() => Content("Version 1");
[HttpGet, MapToApiVersion("2.0")]
public IActionResult GetV2() => Content("Version 2");
}
在这个例子中,DirectorsController的Get方法对应API的1.0版本,而GetV2方法对应API的2.0版本。
可以通过设置[ApiVersion]属性的Deprecated属性来指定API的某个版本是否已弃用:
[ApiVersion("1.0", Deprecated = true)]
[Route("genres")]
public class GenresControllerV1 : Controller
{
[HttpGet]
public IActionResult Get() => Content("Version 1");
}
[ApiVersion("2.0")]
[Route("genres")]
public class GenresControllerV2 : Controller
{
[HttpGet]
public IActionResult Get() => Content("Version 2");
}