ASP.NET Core WebAPI 版本控制
共 15638字,需浏览 32分钟
· 2021-03-12
前言
在日常项目开发中,随着项目需求不断的累加、不断的迭代;项目服务接口需要向下兼容历史版本;前些时候就因为Api接口为做版本管理导致接口对低版本兼容处理不友好。
最近就像了解下如何实现WebApi版本控制,那么版本控制有什么好处呢?
WebApi版本控制的好处
有助于及时推出功能, 而不会破坏现有系统,兼容性处理更友好。 它还可以帮助为选定的客户提供额外的功能。
接下来就来实现版本控制以及在Swagger UI中接入WebApi版本
一、WebApi版本控制实现
通过Microsoft.AspNetCore.Mvc.Versioning 实现webapi 版本控制
创建WebApi项目,添加Nuget包:Microsoft.AspNetCore.Mvc.Versioning
Install-Package Microsoft.AspNetCore.Mvc.Versioning
修改项目Startup文件,使用Microsoft.AspNetCore.Mvc.Versioning
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//根据需要设置,以下内容
services.AddApiVersioning(apiOtions =>
{
//返回响应标头中支持的版本信息
apiOtions.ReportApiVersions = true;
//此选项将用于不提供版本的请求。默认情况下, 假定的 API 版本为1.0
apiOtions.AssumeDefaultVersionWhenUnspecified = true;
//缺省api版本号,支持时间或数字版本号
apiOtions.DefaultApiVersion = new ApiVersion(1, 0);
//支持MediaType、Header、QueryString 设置版本号;缺省为QueryString、UrlSegment设置版本号;后面会详细说明对于作用
apiOtions.ApiVersionReader = ApiVersionReader.Combine(
new MediaTypeApiVersionReader("api-version"),
new HeaderApiVersionReader("api-version"),
new QueryStringApiVersionReader("api-version"),
new UrlSegmentApiVersionReader());
});
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
//使用ApiVersioning
app.UseApiVersioning();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
a)通过ApiVersion标记指定指定控制器或方法的版本号;Url参数控制版本(QueryStringApiVersionReader),如下:
namespace WebAPIVersionDemo.Controllers
{
[ApiController]
[Route("[controller]")]
//Deprecated=true:表示v1即将弃用,响应头中返回
[ApiVersion("1.0", Deprecated = true)]
[ApiVersion("2.0")]public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]{"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = $"v1:{Summaries[rng.Next(Summaries.Length)]}"
})
.ToArray();
}
}
}
通过参数api-version参数指定版本号;调用结果:
![](https://filescdn.proginn.com/25691ee94574e022078f3c36c31eaf48/3a0cf3b28e844a486ac5daa7afd95264.webp)
![](https://filescdn.proginn.com/cce995303e50f7e159a605c349128355/bac3ffd36631f54aa1588fd0c31b0f81.webp)
b)通过Url Path Segment控制版本号(UrlSegmentApiVersionReader):为控制器添加路由方式如下,apiVersion为固定格式
[Route("/api/v{version:apiVersion}/[controller]")]
调用方式:通过调用路径传入版本号,如:http://localhost:5000/api/v1/weatherforecast
![](https://filescdn.proginn.com/af6b8368d338d14cf5b0db17365f6612/af3a560308f9df89ea22d352a3bb9421.webp)
c)通过Header头控制版本号:在Startup中设置(HeaderApiVersionReader、MediaTypeApiVersionReader)
apiOtions.ApiVersionReader = ApiVersionReader.Combine(
new MediaTypeApiVersionReader("api-version"),
new HeaderApiVersionReader("api-version"));
调用方式,在请求头或中MediaType中传递api版本,如下:
![](https://filescdn.proginn.com/1a284dbd460c6ed8075171a94aa8ee33/32949a51259bacc95a071f0d87c8fe92.webp)
![](https://filescdn.proginn.com/b84f1ee6ac5d4d2aab259522b217cea7/dc73bf7835a6f26b728e52e75986a0b7.webp)
其他说明:
a)ReportApiVersions设置为true时, 返回当前支持版本号(api-supported-versions);Deprecated 参数设置为true表示已弃用,在响应头中也有显示(api-deprecated-versions):
![](https://filescdn.proginn.com/cc1feeb3cfb9d6cc7d6043c32ea3297e/133fa5e3aff57d9d6655e9cbb6865f77.webp)
b)MapToApiVersion标记:允许将单个 API 操作映射到任何版本(可以在v1的控制器中添加v3的方法);在上面控制器中添加以下代码,访问v3版本方法
[HttpGet]
[MapToApiVersion("3.0")]
public IEnumerable<WeatherForecast> GetV3()
{
//获取版本
string v = HttpContext.GetRequestedApiVersion().ToString();
var rng = new Random();
return Enumerable.Range(1, 1).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = $"v{v}:{Summaries[rng.Next(Summaries.Length)]}"
})
.ToArray();
}
![](https://filescdn.proginn.com/02dcc65f087c673efc0d0de3b02ef7a8/f39af608ad499321b5ca88e7f8cc1713.webp)
c)注意事项:
1、路径中参数版本高于,其他方式设置版本
2、多种方式传递版本,只能采用一种方式传递版本号
3、SwaggerUI中MapToApiVersion设置版本不会单独显示
二、Swagger UI中版本接入
1、添加包:Swashbuckle.AspNetCore、Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
//swaggerui 包
Install-Package Swashbuckle.AspNetCore
//api版本
Install-Package Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
2、修改Startup代码:
public class Startup
{
/// <summary>
/// Api版本提者信息
/// </summary>
private IApiVersionDescriptionProvider provider;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//根据需要设置,以下内容
services.AddApiVersioning(apiOtions =>
{
//返回响应标头中支持的版本信息
apiOtions.ReportApiVersions = true;
//此选项将用于不提供版本的请求。默认情况下, 假定的 API 版本为1.0
apiOtions.AssumeDefaultVersionWhenUnspecified = true;
//缺省api版本号,支持时间或数字版本号
apiOtions.DefaultApiVersion = new ApiVersion(1, 0);
//支持MediaType、Header、QueryString 设置版本号;缺省为QueryString设置版本号
apiOtions.ApiVersionReader = ApiVersionReader.Combine(
new MediaTypeApiVersionReader("api-version"),
new HeaderApiVersionReader("api-version"),
new QueryStringApiVersionReader("api-version"),
new UrlSegmentApiVersionReader());
});
services.AddVersionedApiExplorer(option =>
{
option.GroupNameFormat = "接口:'v'VVV";
option.AssumeDefaultVersionWhenUnspecified = true;
});
this.provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
services.AddSwaggerGen(options =>
{
foreach (var description in provider.ApiVersionDescriptions)
{
options.SwaggerDoc(description.GroupName,
new Microsoft.OpenApi.Models.OpenApiInfo()
{
Title = $"接口 v{description.ApiVersion}",
Version = description.ApiVersion.ToString(),
Description = "切换版本请点右上角版本切换"
}
);
}
options.IncludeXmlComments(this.GetType().Assembly.Location.Replace(".dll", ".xml"), true);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//……
//使用ApiVersioning
app.UseApiVersioning();
//启用swaggerui,绑定api版本信息
app.UseSwagger();
app.UseSwaggerUI(c =>
{
foreach (var description in provider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
}
});
//……
}
}
3、运行效果:
其他
示例地址:https://github.com/cwsheng/WebAPIVersionDemo
.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
【.NET Core微服务实战-统一身份认证】开篇及目录索引
Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南)
.NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
用abp vNext快速开发Quartz.NET定时任务管理界面