ASP.NET Core WebApi版本控制

前言:

 在日常項目開發中,隨著項目需求不斷的累加、不斷的迭代;項目服務介面需要向下兼容歷史版本;前些時候就因為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參數指定版本號;調用結果:

  

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

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

  調用方式:通過調用路徑傳入版本號,如://localhost:5000/api/v1/weatherforecast

   

  c)通過Header頭控制版本號:在Startup中設置(HeaderApiVersionReader、MediaTypeApiVersionReader

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

   調用方式,在請求頭或中MediaType中傳遞api版本,如下:

   

    

  • 其他說明:

    a)ReportApiVersions設置為true時, 返回當前支援版本號(api-supported-versions);Deprecated 參數設置為true表示已棄用,在響應頭中也有顯示(api-deprecated-versions):

    

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

    

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

  

其他: 

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