Mic*_*sen 2 asp.net-core aspnet-api-versioning
我正在考虑向我们现有的 API 添加版本控制。我们将版本嵌入到 URL 中。
版本控制的要求是应该很容易添加新版本,但并不是所有内容都会改变,我们不想在获得新版本时遍历所有控制器并添加新版本属性。有没有办法告诉 Microsoft.AspNetCore.Mvc.Versioning 无论版本如何,特定方法都应该可用?
我尝试使用 version:apiVersion 和基本路线来装饰我的方法。
[Route("v{version:apiVersion}/customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")
[Route("customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")]
Run Code Online (Sandbox Code Playgroud)
我的配置是这样的(版本号3仅用于测试目的):
services.AddApiVersioning(config =>
{
config.DefaultApiVersion = new ApiVersion(3, 0);
config.AssumeDefaultVersionWhenUnspecified = true;
config.ReportApiVersions = true;
});
Run Code Online (Sandbox Code Playgroud)
使用此配置调用端点时,我得到“与请求 URI 'http://{{host}}/api/customers/{customer}/estates/{estate}/meters/{meter}-{ 匹配的 HTTP 资源”不支持安装}/消费/详情'
一旦我添加 [ApiVersion("3.0")] 属性,一切都会正常。但我的想法是,如果我当前在版本 2 上运行,但对 API 其他部分的更改需要新版本和 API 的默认版本,我不想必须使用此控制器并“升级”版本。它应该继续响应,除非我指定特定的内容。
如果我将 AssumeDefaultVersionWhenUnspecified 更改为 false,我会收到“需要 API 版本,但未指定”。但我预计它只会抢没有版本的路线?
我在这里阅读了有关限制的信息:https://github.com/Microsoft/aspnet-api-versioning/wiki/Known-Limitations#url-path-segment-routing-with-a-default-api-version 但事实并非如此似乎不起作用。
设置AssumeDefaultVersionWhenUnspecified = true是一个被严重滥用的功能。这只是为了促进向后兼容性。一旦您选择 API 版本控制,所有 API 控制器都会有一些隐式或显式的 API 版本。假设某个版本提供了一种处理“原始”未命名版本的机制,否则会破坏不知道在请求中包含 API 版本的现有客户端。
“有什么方法可以告诉 Microsoft.AspNetCore.Mvc.Versioning 某个特定方法应该可用,无论版本如何?”
是的,但我不完全确定这就是您要找的。API 可以是版本中立的,这意味着它将接受任何和所有 API 版本,包括根本不接受。这对于某些类型的 API(例如/ping运行状况检查或DELETE通常不会随时间变化的 API)很有用。这样的 API 可以用[ApiVersionNeutral]. 这可以适用于控制器上的所有 API 或特定操作。请注意,一旦选择了这条路径,“就只能有一条”。
没有您的设置的完整图片。您似乎正在向一组现有 API 添加 API 版本控制。主要目的之一DefaultApiVersion是在没有其他信息可用时设置默认 API 版本。如果您没有应用任何 API 版本 - 例如,使用属性,那么这将是所有 API 的隐式 API 版本。这使您无需改造所有现有的控制器和代码。不太明显的是,一旦应用任何显式 API 版本,隐式规则就会被忽略。这确保了隐式版本可以被取消。默认版本通常并不重要。它只是您指示最初的 API 版本的一种方式。当祖父辈时这是最相关的现有 API
鉴于您的配置:
// implicitly 3.0 because DefaultApiVersion = 3.0 and there
// are no explicit versions from attributes or conventions
[Route("customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")]
public class CustomerController : ControllerBase
{
}
Run Code Online (Sandbox Code Playgroud)
具有隐式版本控制的祖父控制器
// explicitly 2.0 due to attributes; DefaultApiVersion is ignored
[ApiVersion("2.0")]
[Route("v{version:apiVersion}/customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")
[Route("customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")]
public class CustomerController : ControllerBase
{
}
Run Code Online (Sandbox Code Playgroud)
具有显式版本控制的控制器
除支持向后兼容的原始API版本外,所有API版本都是显式且离散的;这是设计使然。模糊匹配不会以可预测的方式工作,因此精确匹配非常重要。
您似乎正在描述 API 版本交错 - 例如,在单个控制器实现上实现多个 API 版本。我想它可能看起来像:
[ApiVersion("2.0")]
[ApiVersion("3.0")]
[Route("v{version:apiVersion}/customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")
[Route("customers/{customerId}/estates/{estateId:int}/meters/{meterNumber}-{installationId}/consumption/detail")]
public class CustomerController : ControllerBase
{
// implicitly maps to 2.0 from the controller, but does not
// match 3.0 because there is an explicit 3.0 mapping
[HttpGet]
public IActionResult Get(
string customerId,
int estateId,
string meterNumber,
string installationId ) => Ok();
// explicitly maps to 3.0 only
[MapToApiVersion("3.0")]
[HttpGet]
public IActionResult GetV3(
string customerId,
int estateId,
string meterNumber,
string installationId ) => Ok();
// explicitly maps to 3.0 only
// a 2.0 request produces 405
[MapToApiVersion("3.0")]
[HttpPut]
public IActionResult Put(
string customerId,
int estateId,
string meterNumber,
string installationId
[FromBody] ComsumptionDetail detail ) => Ok();
}
Run Code Online (Sandbox Code Playgroud)
具有版本交错的控制器
只能DefaultApiVersion应用单个隐式 API 版本。这意味着永远不会发生与它的交错。一旦开始显式添加版本,您还必须开始包含隐式版本,因为没有其他方法可以指示隐式版本不应再匹配。
在路由定义和 API 版本映射方面,有多种方法可用于最大限度地减少代码改动。VersionByNamespaceConvention是您可以应用的内置约定,它将从控制器类型的 .NET 命名空间派生 API 版本。这使得添加、删除和组织控制器及其 API 版本变得非常容易。他们还可以使用交错,因为映射是可加的,但这可能难以维护。您也可以定义自己的约定。
双路由注册是按 URL 段进行版本控制的结果。它是最不 RESTful 的版本控制方法,因为它违反了统一接口约束。没有其他版本控制方法存在此问题。我建议不要浮动默认路由和 API 版本映射,因为您很可能在某些时候破坏客户端。如果您只是使用双路由来向后兼容原始 API 版本,那么应该没问题。当您最终为未来的 API 版本创建新控制器时,模板中将只有一条包含该 API 版本的路由。
| 归档时间: |
|
| 查看次数: |
3475 次 |
| 最近记录: |