如何解决Service Fabric Web API 版本控制问题 问题 1问题 2观察 1
我正在处理具有多个无状态服务的服务结构项目。当我尝试在下面的代码中添加版本控制
[Authorize]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class SessionController : Controller
{
...
}
稍后使用 Postman 或使用我为调用此服务而制作的某些客户端 winforms 应用程序调用该服务时,它不起作用。当我说它不起作用时,我的意思是它不是在寻找我放在控制器中的特定版本。
例如 我正在调用 http://localhost:1234/api/v1.0/session/set-session,正如您在我的控制器中看到的那样,我只有 2.0 版。现在,无论我输入什么版本号,我的 API 都会以这种方式或其他方式受到影响。
services.AddApiVersioning(options => {
options.DefaultApiVersion = new ApiVersion(2,0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ReportApiVersions = true;
options.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
});
具体的 API 调用如下所示:
[HttpPost]
[Route("set-session")]
public async Task<IActionResult> SetSession([FromBody] SessionModel model)
{ ... }
谁能告诉我我缺少什么,或者服务结构根本不支持 api 版本控制? 谢谢。
解决方法
您的解决方案是否适用于本地?根据我所看到的,我会怀疑 - 不。这应该与 Service Fabric 完全无关。
问题 1
我看到您的基类继承自 Controller
,这是允许的,但通常是 ControllerBase
。不用担心,仅供参考。问题的关键在于很可能您的控制器没有应用 [ApiController]
属性。 API Versioning 定义了 IApiControllerSpecification
和 IApiControllerFilter
,用于过滤哪些控制器应该被视为 API。这对于构建 UI 和 API 部分混合的应用程序的开发人员很重要。控制器是 ASP.NET Core 中的控制器,早期很难区分这两者。现在有一个内置的 IApiControllerSpecification
,可以将任何应用了 [ApiController]
的控制器视为 API。这可以使用 ApiVersioningOptions.UseApiBehavior = false
更改、替换或完全禁用。
如果您的库/应用程序只是 API,您可以使用以下方法一次性装饰所有控制器:
[assembly: ApiController]
由于您的控制器当前未被视为 API,因此所有与路由匹配的请求都被定向到那里。值 1.0
被视为任意字符串而不是 API 版本。这就是它完全匹配而不是 HTTP 400 的原因。我怀疑您必须只有一个 API,它被定义为 2.0
;否则,我会期待一个 AmbiguousActionException
。
问题 2
您的示例显示您正在尝试按 URL 段进行版本控制,但您已将选项配置为仅考虑标头 x-api-version
。此选项应配置为以下之一:
网址段(仅)
options.ApiVersionReader = new UrlSegmentApiVersionReader();
网址段和标题
// registration order is irrelevant
options.ApiVersionReader = ApiVersionReader.Combine(
new UrlSegmentApiVersionReader(),new HeaderApiVersionReader("x-api-version"));
默认(查询字符串和 URL 段)
// NOTE: this is the configuration
// options.ApiVersionReader = ApiVersionReader.Combine(
// new QueryStringApiVersionReader(),// new UrlSegmentApiVersionReader());
旁注
根据定义,使用 URL 段和标头版本控制方法没有意义。您有一个需要 API 版本的路由。客户端将始终必须在每个请求中包含 API 版本,因此没有必要同时支持标头。
如果你定义了 2 条路由,那就有意义了:
[Route("api/[controller]")] // match by header
[Route("api/v{version:apiVersion}/[controller]")] // match by url segment
按 URL 段进行版本控制虽然很常见,但却是最不符合 REST 的。它违反了Uniform Interface 约束。这个问题说明了该方法的另一个问题。查询字符串、标头、媒体类型或它们的任何组合都将与以下单个路由模板一起使用:[Route("api/[controller]")]
观察 1
您已配置 options.AssumeDefaultVersionWhenUnspecified = true
。当按 URL 段进行版本控制时,这将无效。不可能在模板中间提供路由参数的默认值。如果未指定 api/value/{id}/subvalues
,{id}
也是如此。
如果您:
此选项将有效:- 添加第二个没有 API 版本参数的路由模板
- 您更新了版本控制策略以不使用 URL 段
需要注意的是,这是一个被高度滥用的功能。它旨在祖父在以前没有显式版本控制的现有服务中,因为添加它会破坏现有客户端。如果这不是您的用例,您应该意识到这一点。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。