希望有人尝试过与MVC 6和Swagger中的版本化API类似的东西,以显示有关不同版本的文档.
我在这个ASP.NET 5存储库中使用MVC 6中推荐的API版本.我所做的唯一改变是GetVersion方法从请求的自定义http头读取api版本:
//in VersionRangeValidator.cs
public static string GetVersion(HttpRequest request)
{
//return request.Query["version"];
if (!string.IsNullOrWhiteSpace(request.Headers[Constants.CommonRoutingDefinitions.ApiVersionSegmentName]))
{
return request.Headers[Constants.CommonRoutingDefinitions.ApiVersionSegmentName];
}
return Constants.CommonRoutingDefinitions.CurrentApiVersion;
}
Run Code Online (Sandbox Code Playgroud)
我有一个像这样的控制器:
[Route("api/[controller]")]
[Produces(Constants.MediaTypeNames.ApplicationJson)]
public class TagsController : Controller
{
private readonly ITagService _tagService;
public TagsController(ITagService tagService)
{
_tagService = tagService;
}
/// <summary>
/// Version 1 by default
/// </summary>
/// <returns>All the tags</returns>
[HttpGet]
[Produces(typeof(IEnumerable<Tag>))]
public IEnumerable<Tag> GetTags()
{
IEnumerable<Tag> tags = _tagService.GetTags();
return tags;
}
/// <summary>
/// Version 2
/// </summary> …Run Code Online (Sandbox Code Playgroud) swagger swagger-ui asp.net-core-mvc api-versioning asp.net-core
我是api版本控制的新手,所以我的问题是:
1)此文件夹结构是否正确?
/app
/controllers
/Api
/v1
/UserController.php
/v2
/UserController.php
Run Code Online (Sandbox Code Playgroud)
路线:
Route::group(['prefix' => 'v1'], function () {
Route::get('user', 'Api\v1\UserController@index');
Route::get('user/{id}', 'Api\v1\UserController@show');
});
Route::group(['prefix' => 'v2'], function () {
Route::get('user', 'Api\v2\UserController@index');
Route::get('user/{id}', 'Api\v2\UserController@show');
});
Run Code Online (Sandbox Code Playgroud)
2)关于模型和事件的文件夹结构如何,我应该为每个版本制作模型吗?
我有一个 ASP.NET Core 3.1 API,我正在为我的一个控制器引入新版本。我正在使用Microsoft.AspNetCore.Mvc.Versioning NuGet 包,并且已将新版本设置为默认版本。我的所有其他控制器都应适用于旧版本(1.0)和新版本(1.1)。
例如:
[ApiVersion("1.0", Deprecated = true)]
public class MySampleController
{
}
[ApiVersion("1.1")]
public class MyNewSampleController
{
}
[ApiVersion("1.0", Deprecated = true)]
[ApiVersion("1.1")]
public class AllOtherController
{
}
Run Code Online (Sandbox Code Playgroud)
问题:
我真的必须将所有版本添加到所有控制器吗?
有更好/正确的方法来处理这个问题吗?
我尝试使用 [ApiVersionNeutral] 但这似乎不正确,根据文档,应该只在特殊情况下使用。如果我不添加 [ApiVersion] 属性,则默认为新的 1.1 版本,1.0 不再有效。
由于这是我的第一个问题,我希望它符合指导方针:)
c# api-versioning asp.net-core asp.net-core-webapi asp.net-core-3.1
我之前为我的观点创建了一些测试。像那样
class TestUserRegistrationViewUserCreate(APITestCase):
def setUp(self):
self.factory = APIRequestFactory()
def test_create_user(self):
data = {
'phone_number': '+79513332211',
'password': 'qwerty'
}
request = self.factory.post(reverse('user'), data=data)
response = CustomUserAPIView.as_view()(request)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
Run Code Online (Sandbox Code Playgroud)
一切都很好,直到我被要求添加 API 版本控制。
DRF 支持本地版本控制http://www.django-rest-framework.org/api-guide/versioning/ 所以我只是使用它并将基于命名空间的版本控制添加到我的 API 中
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning'
}
Run Code Online (Sandbox Code Playgroud)
现在我需要重写我的视图单元测试以支持版本控制。
这个问题是,为了通过 获得版本化的 url reverse,我必须使用
from rest_framework.reverse import reverse
reverse('bookings-list', request=request)
Run Code Online (Sandbox Code Playgroud)
就像在文档中一样。
但是我request在测试中没有对象,因为我正在自己制作一个对象,并且需要制作它的版本化 url。
我该怎么办?
PS 我可以在不使用 DRF 的情况下实现版本控制,使用视图装饰器和几个 utils 函数来解决这个问题,但是当我重新发明轮子时,这对我来说感觉很糟糕。另外,我也可能会忘记一些边缘情况。
我正在为 Webapi 服务中的所有错误创建一个包库。该库将用于为 BadRequest、BadArgument、ApiVersionsing 等相关错误提供自定义响应。我需要帮助自定义 Apiversion 相关错误 - ApiVersionUnspecified、UnsupportedApiVersion、InvalidApiVersion、AmbiguousApiVersion。我已经按照这篇文章为我的项目包含 api-versioning - https://www.hanselman.com/blog/ASPNETCoreRESTfulWebAPIVersioningMadeEasy.aspx
我已经检查了上述包的 github wiki,发现“根据所需的行为,您可以扩展 DefaultErrorResponseProvider 或者您可以从 stratch 实现您自己的 IErrorResponseProvider。
要连接备用错误响应行为,请将默认提供程序替换为您自己的:”
options => options.ErrorResponses = new MyErrorResponseProvider();
Run Code Online (Sandbox Code Playgroud)
然而; 我不太明白如何自定义 MyErrorResponseProvider 类中的默认错误响应。有人可以为我提供任何示例,以便我可以开始使用吗?
提前致谢!
c# error-handling custom-error-handling .net-core api-versioning
我想准备我的.NET Core Web API项目,以便可以根据REST服务标准来管理和记录API的多个版本。
我正在使用带有NSwag(v11.18.2)的.NET Core 2.1。我还安装了Microsoft.AspNetCore.Mvc.Versioning NuGet程序包。
我已经在Google上搜索了一些配置示例,但是我发现的唯一有用的链接是this。
现在,我可以获取两个API版本的Swagger页面,但存在一些问题:
config的设置(Title,Description在任何2路等)生效。仅当我将它们添加到每个单独的配置中时,它才起作用。因此,我也想知道是否有可能避免这种情况,因为API的常规配置可以是版本无关的(标题,说明等...)。因此,通过该示例,我的实际配置如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ReportApiVersions = true;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSwaggerWithApiExplorer(config =>
{
config.GeneratorSettings.OperationProcessors.TryGet<ApiVersionProcessor>().IncludedVersions = new[] { "1.0" };
config.SwaggerRoute = "v1.0.json";
});
app.UseSwaggerWithApiExplorer(config =>
{
config.GeneratorSettings.OperationProcessors.TryGet<ApiVersionProcessor>().IncludedVersions = new[] { "2.0" …Run Code Online (Sandbox Code Playgroud) 我正在使用REST API,因此我将不得不很快引入一些重大更改,因此需要v2。尽管仍并行支持v1,但仍需要几个月的时间,以便让我们的客户有时间在准备好新版本时切换到新的API。我们的API是通过共享云提供的,并且我们所有的客户都共享相同的系统后端,尤其是单个共享数据库。
我找到了很多有关REST API版本控制的文章,但它们更多是从客户端的角度或从高级设计的角度来看的。这并不是我真正关心的问题,我们的API已经在URI中提供了版本控制,因此提供带有/ v2基本路径的服务将不是问题。
但是我问自己,我将如何实际实现它,而我还没有真正找到好的文章。我真的不想分支我的项目的v2,然后将v1和v2分别构建和部署为单独的应用程序,因为那样的话,我将在两个应用程序中进行维护,错误修复,配置更改等,这是双重工作并且通常冗余的危险(即:版本之间可能存在不一致)。同样,v2当然在每个服务中也不相同,因此大多数代码仍将相同。
是否有关于如何在单个应用程序中技术地实现REST API的最佳实践,该应用程序向外部提供多个版本,并且在其中共享了一些代码(即:v2 / someService将在内部重定向到v1 / someService),而实际新服务中编码了差异?也许甚至还有一些框架可以帮助您设计?如果有帮助,该应用程序使用Spring MVC用Java编码。
感谢您提供有关解决此问题的提示或资源。谢谢!
我有一个使用.net core 2.2 的Web API 项目(也许存在问题。)
这些路由正在等待 OpenIdDict 的 OAuth 授权,但这对我来说完全没问题。我正在尝试一种非常简单的方法:
startup.cs 仅包含:
services.AddApiVersioning();
Run Code Online (Sandbox Code Playgroud)
API 控制器具有三种不同的路由用于测试目的。请注意,控制器本身没有 [Route()] 或 [ApiVersion()] 注释。
[HttpGet]
[Authorize]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/vt")]
public IActionResult GetVt20()
{
return Ok("2.0");
}
[HttpGet]
[Authorize]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/vt")]
public IActionResult GetVt10()
{
return Ok("1.0");
}
Run Code Online (Sandbox Code Playgroud)
如果我执行授权请求,例如
http://localhost:27713/api/v1.0/vt
Run Code Online (Sandbox Code Playgroud)
.net core 用 BadRequest 回答:
{"error":{"code":"UnsupportedApiVersion","message":"The HTTP resource that matches the request URI 'http://localhost:27713/api/v1.0/vt' does not support the API version '1.0'.","innerError":null}}
Run Code Online (Sandbox Code Playgroud)
我缺少什么?
经过多次尝试和阅读文章后,我决定将我的问题放在这里。我想要的是:我正在研究应用程序的 api 版本控制。.NET Core(包)支持的版本格式Microsoft.AspNetCore.Mvc.Versioning是Major.Minor,这就是我想在我从事的项目中使用的版本格式。我想要的是一个后备版本,以防客户端未指定次要版本。我正在使用 .NET core 2.2,并使用api-version标头中指定的内容。相应的 API 版本控制配置如下所示:
services.AddApiVersioning(options => {
options.ReportApiVersions = true;
options.ApiVersionReader = new HeaderApiVersionReader("api-version");
options.ErrorResponses = new ApiVersioningErrorResponseProvider();
});
Run Code Online (Sandbox Code Playgroud)
我每个版本都有以下两个控制器:(为了解决这个问题,控制器被简化了):
[ApiVersion("1.0")]
[Route("api/[controller]")]
public class ValueControllerV10 : Controller
{
[HttpGet(Name = "collect")]
public String Collect()
{
return "Version 1.0";
}
}
[ApiVersion("1.1")]
[Route("api/[controller]")]
public class ValueControllerV11 : Controller
{
[HttpGet(Name = "collect")]
public String Collect()
{
return "Version 1.1";
}
}
Run Code Online (Sandbox Code Playgroud)
如果客户端指定,api-version=1.0则使用 ValueControllerV10。当然,如果客户端指定api-version=1.1,则按预期使用 ValueControllerV11。
现在我的问题来了。如果客户端指定api-version=1(因此只有主要版本而没有次要版本),则使用 ValueControllerV10。如果我没记错的话,这是因为 …
var constraintResolver = new DefaultInlineConstraintResolver()
{
ConstraintMap =
{
["apiVersion"] = typeof( ApiVersionRouteConstraint )
}
};
config.MapHttpAttributeRoutes(constraintResolver);
config.AddApiVersioning(o => o.AssumeDefaultVersionWhenUnspecified = true);
[ApiVersion("2.05")]
[RoutePrefix("api/v{version:apiVersion}/ger")]
public class caGerController
[Route("~/api/ger/getDetail")]
[Route("getDetail")]
GetGerData
[ApiVersion("1")]
[RoutePrefix("api/v{version:apiVersion}/gerDetail")]
public class caGerDetailsController
caGerController
[Route("~/api/gerDetail/getDetail")]
[Route("getDetail")]
GetGerData
>> GetGerData
Run Code Online (Sandbox Code Playgroud)
结果:
两个 URL 都与 v1 版本 ROUTE 一起使用。
第二个 URL 既适用于 v1 也适用于没有 v1 路由的直接路由,即 [Route("~/api/gerDetail/getDetail")]
问题:第一个 URL 仅适用于 v1,它不适用于像“[Route("~/api/ger/getDetail")]”这样的直接路由,并收到如下错误:
"Error": { "Code": "ApiVersionUnspecified", "Message": "API 版本是必需的,但未指定。" }
如何解决这个问题?当我从 2.05 更改为 1.0 时,它可以工作,但 2.0 或 2.05 都不起作用。是否需要单独的文件夹?
routes asp.net-web-api asp.net-web-api-routing api-versioning
api-versioning ×10
.net-core ×4
c# ×4
asp.net-core ×2
rest ×2
api ×1
asp.net-mvc ×1
django ×1
java ×1
laravel ×1
nswag ×1
php ×1
python ×1
routes ×1
swagger ×1
swagger-ui ×1
testing ×1
versioning ×1