場景:

  在利用.net core進行api介面開發時,經常會因為需求,要開發實現統一功能的多版本的介面。比如版本V1是給之前使用者使用,然後新使用者有新需求,這時候可以單獨給這個使用者寫介面,也可以在V1基礎上寫版本V2,這樣V1的使用者要使用V2的介面,只有稍微改一下就可以了。

實現:

  1.APIVersion

  首先需要安裝Nuget包:Microsoft.AspNetCore.Mvc.Versioning  以及  Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer

  然後在ConfigureServices中新增以下內容;

 1             // API介面版本
2 services.AddApiVersioning(o => {
3 o.ReportApiVersions = true;
4 o.AssumeDefaultVersionWhenUnspecified = true;
5 //o.ApiVersionReader = new HeaderApiVersionReader("version");
6 o.DefaultApiVersion = new ApiVersion(1, 0);
7 });
8 services.AddVersionedApiExplorer( o => {
9 o.GroupNameFormat = "'v'VVV";
10 o.SubstituteApiVersionInUrl = true;
11 });

  同時在Configure中新增以下內容:

app.UseApiVersioning();

  ApiVersion用來配置預設版本,版本位置等,這裡的ApiVersionReader可以設定api版本位置,比如是http中的Header位置,還是放在請求中。

  VersionedApiExplorer用來版本管理,其中的GroupNameFormat是api組名格式,而SubstituteApiVersionInUrl 是設定在url中替換版本

  之後在控制器上新增版本,如下:

    /// <summary>
/// 角色相關
/// </summary>
[ApiVersion("2.0")]
[TypeFilter(typeof(AuthFilter))]
[ApiController]
[Route("api/v{version:apiVersion}/[controller]/[action]")]
public class RoleController:ControllerBase
{
/// <summary>
/// 新增角色,版本2
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost,MapToApiVersion("2.0")]
public Response<DTO_Id> AddRole(DTO_AddOrUpdate_Role_V2 req)
{
}
}
   /// <summary>
/// 角色相關,版本1
/// </summary>
[ApiVersion("1.0")]
[TypeFilter(typeof(AuthFilter))]
[ApiController]
[Route("api/v{version:apiVersion}/[controller]/[action]")]
public class RoleController:ControllerBase
{
/// <summary>
/// 新增角色
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost]
public Response<DTO_Id> AddRole(DTO_AddOrUpdate_Role req)
{ }
}

  這裡在apiVersion中設定控制器版本,同時可以通過引數不同來過載函式。這樣就實現了版本控制

  2.swagger

  首先先匯入nuget包,Swashbuckle.AspNetCore

  在ConfigureService中配置swaager,如下;

       var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
// swagger
services.AddSwaggerGen(c =>
{ // 排序方式
c.OrderActionsBy(o => o.HttpMethod);
foreach (var item in provider.ApiVersionDescriptions)
{
c.SwaggerDoc(item.GroupName, new OpenApiInfo
{
Title = "WebAPI" + item.GroupName,
Version = item.ApiVersion.MajorVersion.ToString() + "." + item.ApiVersion.MinorVersion
}); }
c.OperationFilter<GlobalHttpHeaderOperationFilter>();
// 過載方式
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); foreach (var name in Directory.GetFiles(AppContext.BaseDirectory, "*.*",
SearchOption.AllDirectories).Where(f => Path.GetExtension(f).ToLower() == ".xml"))
{
c.IncludeXmlComments(name, includeControllerXmlComments: true);
}
});

  這裡需要獲取APIversion中各個版本的資訊,可以利用services.BuildServiceProvider().GetRequiredService<>獲取。

c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

  同時這句是為了讓swaager支援函式過載。而且可以通過OrderActionsBy來設定排序順序。

  最後在Configure中使用swagger。

        app.UseSwagger();

            var provider = _services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
app.UseSwaggerUI(c =>
{
foreach (var item in provider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"/swagger/{item.GroupName}/swagger.json", item.GroupName);
}
});

  為了獲取serviceCollection中的apiversion資訊,需要新增如下;

private IServiceCollection _services;

  在ConfigureServices中新增:

_services = services;

  這樣就能在Configure中使用ServiceCollention中的service了。

結果:

  

  可以通過swagger中的definition來選擇介面版本,也能看到介面版本顯示先url中。