16

ASP.NET Core WebApi版本控制

 3 years ago
source link: http://www.cnblogs.com/cwsheng/p/14426490.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

前言:

在日常项目开发中,随着项目需求不断的累加、不断的迭代;项目服务接口需要向下兼容历史版本;前些时候就因为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();
        });
    }
}
  • WebApi设置版本:

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参数指定版本号;调用结果:

3yQzM3b.png!mobile

YVru6vY.png!mobile

b)通过Url Path Segment控制版本号( UrlSegmentApiVersionReader ):为控制器添加路由方式如下,apiVersion为固定格式

[Route("/api/v{version:apiVersion}/[controller]")]

调用方式:通过调用路径传入版本号,如: http://localhost:5000/api/v1/weatherforecast

yai67ve.png!mobile

c)通过Header头控制版本号:在Startup中设置( HeaderApiVersionReader、MediaTypeApiVersionReader

apiOtions.ApiVersionReader = ApiVersionReader.Combine(
                new MediaTypeApiVersionReader("api-version"),
                new HeaderApiVersionReader("api-version"));

调用方式,在请求头或中MediaType中传递api版本,如下:

ziYjErQ.png!mobile

veEBZn2.png!mobile

  • 其他说明:

a)ReportApiVersions设置为true时, 返回当前支持版本号(api-supported-versions);Deprecated 参数设置为true表示已弃用,在响应头中也有显示(api-deprecated-versions):

FrmyqaI.png!mobile

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();
}

uI7JzqB.png!mobile

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、运行效果:

juEjIra.gif!mobile

其他:

示例地址:https://github.com/cwsheng/WebAPIVersionDemo


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK