API 在 C# 中没有重复代码的版本控制
API versioning without duplicate code in C#
我有一种情况,我正在向 API 添加版本控制,因此某些 API 函数的路由发生了变化。我还将一些方法从 POST 更改为 GET,因为它更有意义。
我想弃用旧路线,以便人们开始使用新路线。我希望旧路由绑定到我的 API 的 v1,而新路由绑定到 v2。
我通过复制所有函数并用正确的路由、方法和 api 版本标记它们来实现这个工作,但我希望有一个更清晰的解决方案。
下面我的 'cleaner' 示例显然不起作用,因为在这种情况下你得到 4 个函数,它们都已弃用。
你得到:
- HTTPGET /频道
- HTTPPOST/频道
- HTTPGET /api/v2/channels/get
- HTTPPOST/api/v2/channels/get
/// <summary>
/// Gets a list of all channels
/// </summary>
/// <returns>List of all channels</returns>
[HttpPost, Route("~/channels"), ApiVersion("1.0"), Obsolete("Obsolete, please use /api/v2/channels/get")]
[HttpGet, Route("Get"), ApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannels()
{
return await _context.Monitors.ToListAsync();
}
有什么方法可以让它工作吗?
您可以创建两个单独的函数作为 API 内部逻辑的“访问点”。其中一个可以标记为过时并使用旧路线,另一个将使用新路线。然后您可以创建第三个函数,其中包含 API.
的实际逻辑
// The obsolete access point
[HttpPost, Obsolete("Obsolete, please use /api/v2/channels/get"), ApiVersion("1.0")]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannelsOld()
{
return await GetChannelsLogic();
}
// The new access point
[HttpGet, ApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannelsNew()
{
return await GetChannelsLogic();
}
//Marked as NonAction so the method can't be accessed by a request. This is not necessary depending on the setup of your project.
[NonAction]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannelsLogic()
{
// Perform some other logic
return await _context.Monitors.ToListAsync();
}
尝试使用
[HttpPost("~/channels"), ApiVersion("1.0"), Obsolete("Obsolete, please use /api/v2/channels/get")]
[HttpGet("Get"), ApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<string>>> GetChannels()
{
return new List<string>();
}
这样你就只能有两条路线
- HTTPPOST /频道
- HTTPGET /api/v2/channels/get
我有一种情况,我正在向 API 添加版本控制,因此某些 API 函数的路由发生了变化。我还将一些方法从 POST 更改为 GET,因为它更有意义。
我想弃用旧路线,以便人们开始使用新路线。我希望旧路由绑定到我的 API 的 v1,而新路由绑定到 v2。 我通过复制所有函数并用正确的路由、方法和 api 版本标记它们来实现这个工作,但我希望有一个更清晰的解决方案。
下面我的 'cleaner' 示例显然不起作用,因为在这种情况下你得到 4 个函数,它们都已弃用。
你得到:
- HTTPGET /频道
- HTTPPOST/频道
- HTTPGET /api/v2/channels/get
- HTTPPOST/api/v2/channels/get
/// <summary>
/// Gets a list of all channels
/// </summary>
/// <returns>List of all channels</returns>
[HttpPost, Route("~/channels"), ApiVersion("1.0"), Obsolete("Obsolete, please use /api/v2/channels/get")]
[HttpGet, Route("Get"), ApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannels()
{
return await _context.Monitors.ToListAsync();
}
有什么方法可以让它工作吗?
您可以创建两个单独的函数作为 API 内部逻辑的“访问点”。其中一个可以标记为过时并使用旧路线,另一个将使用新路线。然后您可以创建第三个函数,其中包含 API.
的实际逻辑 // The obsolete access point
[HttpPost, Obsolete("Obsolete, please use /api/v2/channels/get"), ApiVersion("1.0")]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannelsOld()
{
return await GetChannelsLogic();
}
// The new access point
[HttpGet, ApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannelsNew()
{
return await GetChannelsLogic();
}
//Marked as NonAction so the method can't be accessed by a request. This is not necessary depending on the setup of your project.
[NonAction]
public async Task<ActionResult<IEnumerable<DbChannel>>> GetChannelsLogic()
{
// Perform some other logic
return await _context.Monitors.ToListAsync();
}
尝试使用
[HttpPost("~/channels"), ApiVersion("1.0"), Obsolete("Obsolete, please use /api/v2/channels/get")]
[HttpGet("Get"), ApiVersion("2.0")]
public async Task<ActionResult<IEnumerable<string>>> GetChannels()
{
return new List<string>();
}
这样你就只能有两条路线
- HTTPPOST /频道
- HTTPGET /api/v2/channels/get