Service Fabric Web API 版本控制问题 问题 1问题 2观察 1

如何解决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 都会以这种方式或其他方式受到影响。

我在 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 版本控制? 谢谢。

解决方法

您的解决方案是否适用于本地?根据我所看到的,我会怀疑 - 不。这应该与 Service Fabric 完全无关。

问题 1

我看到您的基类继承自 Controller,这是允许的,但通常是 ControllerBase。不用担心,仅供参考。问题的关键在于很可能您的控制器没有应用 [ApiController] 属性。 API Versioning 定义了 IApiControllerSpecificationIApiControllerFilter,用于过滤哪些控制器应该被视为 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?