Service Fabric Web API 版本控制问题
Posted
技术标签:
【中文标题】Service Fabric Web API 版本控制问题【英文标题】:Service Fabric Web API Versioning issue 【发布时间】:2021-07-31 16:11:28 【问题描述】:我正在开发一个包含多个无状态服务的服务结构项目。当我尝试在下面的代码中添加版本控制时
[Authorize]
[ApiVersion("2.0")]
[Route("api/vversion:apiVersion/[controller]")]
public class SessionController : Controller
...
稍后使用 Postman 或使用我为调用此服务而制作的某些客户端 winforms 应用程序调用该服务时,它不起作用。当我说它不起作用时,我的意思是它不是在寻找我放置在控制器中的特定版本。
例如 我正在调用 http://localhost:1234/api/v1.0/session/set-session,正如您在我的控制器中看到的那样,我只有 2.0 版。现在,无论我输入什么版本号,我的 API 都会以这种或另一种方式受到影响。
我在 Startup.cs 中添加了代码
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 版本控制? 谢谢。
【问题讨论】:
【参考方案1】:您的解决方案在本地有效吗?根据我所看到的,我会怀疑 - 不。这应该与 Service Fabric 完全无关。
问题 1
我看到你的基类继承自Controller
,这是允许的,但通常是ControllerBase
。不用担心,仅供参考。问题的症结可能是您的控制器没有应用[ApiController]
属性。 API 版本控制定义了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();
URL 段和标头
// 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/vversion:apiVersion/[controller]")] // match by url segment
按 URL 段进行版本控制虽然很常见,但 RESTful 最少。它违反了 统一接口 约束。这个问题展示了该方法的另一个问题。查询字符串、标头、媒体类型或它们的任何组合都将使用单个路由模板:
[Route("api/[controller]")]
观察 1
您已配置options.AssumeDefaultVersionWhenUnspecified = true
。在按 URL 段进行版本控制时,这将无效。在模板中间提供路由参数的默认值是不可能的。如果未指定 id
,api/value/id/subvalues
也是如此。
如果您满足以下条件,则此选项将生效:
添加第二个没有 API 版本参数的路由模板 您将版本控制策略更新为不使用 URL 段需要注意的是,这是一个被高度滥用的功能。它旨在祖父在以前没有明确版本控制的现有服务中,因为添加它会破坏现有客户端。如果这不是您的用例,您应该意识到这一点。
【讨论】:
是的,你对一切都是正确的。我在 Startup.cs 中清除了版本控制配置,并用 [ApiController] 装饰了控制器,效果很好。当我用错误的版本调用 api 时,我得到了 UnsupportedApiVersion 响应,而当调用了正确版本的 api 时,我得到了正确的响应。非常感谢伙计。我会投票给这个答案作为正确的答案,但由于我的声誉不足,其他人无法看到它。以上是关于Service Fabric Web API 版本控制问题的主要内容,如果未能解决你的问题,请参考以下文章
具有外部和内部端点的 Service Fabric Web Api
Web API Service Fabric 应用程序提供未经授权的