• ASP.NET Core – Web API Versioning


    前言

    项目持续维护, API 就需要版本控制. ASP.NET Core 有官方的插件专门处理 API 版本控制哦.

    主要参考

    Your Guide to REST API Versioning in ASP.NET Core

    Asp.Net.Core WebApi 4种版本控制的方式

    How to use API versioning in ASP.NET Core

    ASP.NET Core WebApi版本控制的实现 (有讲到 swagger 哦)

    Asp.Net Core 5 - API Versioning

    Github aspnet-api-versioning

    安装 nuget

    dotnet add package Microsoft.AspNetCore.Mvc.Versioning

    Program.cs

    using Microsoft.AspNetCore.Mvc;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddApiVersioning(options =>
    {
        options.AssumeDefaultVersionWhenUnspecified = true; // 如果请求没有声明就使用默认版本
        options.DefaultApiVersion = new ApiVersion(1, 0); // 默认版本
        options.ReportApiVersions = true; // 在 header 返回支持的版本 (尤其用于 deprecated 弃用的 API)
    });
    //builder.Services.AddSwaggerGen();
    var app = builder.Build();
    if (app.Environment.IsDevelopment())
    {
        //app.UseSwagger();
        //app.UseSwaggerUI();
    }
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.MapControllers();
    app.Run();

    这个是 ASP.NET Core 6.0 的版本哦, 主要看 .AddApiVersioning, Swagger 我注释掉是因为 versioning 和 swagger 有时候会打架. 

    By default, 它是用 request query string 声明 version 的, 这个通常我们不喜欢,我们喜欢在 url path 里面声明. 最好也不要有 default version 的概念. 因为竟然都分 version 了咯, 就分清清楚楚丫.

    两种管理方式

    1. 一个 controller 多个 version 

    namespace WebApiVersioning.Controllers
    {
        [ApiController]
        // 表示这个 Controller 支持 1.0 和 2.0
        [ApiVersion("1.0", Deprecated = true)] // Deprecated 表示废弃了, 会在返回的 header 表示, 虽然是废弃了, 但是依然会跑和 response 的哦 (自行处理)
        [ApiVersion("2.0")]
        [Route("api/v{version:apiVersion}/[controller]")] // 声明 version in path
        public class WeatherForecastController : ControllerBase
        {
            [HttpGet(Name = "GetWeatherForecast"), MapToApiVersion("1.0")] // 通过 MapToApiVersion 声明这个 action 是 for 哪个 version 
            public IEnumerable<WeatherForecast> Get_v1() // 名字是 v1
            {
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                })
                .ToArray();
            }
    
            [HttpGet(Name = "GetWeatherForecast"), MapToApiVersion("2.0")]
            public IEnumerable<WeatherForecast> Get_v2() // 名字是 v2
            {
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                })
                .ToArray();
            }
    
            private static readonly string[] Summaries = new[]
            {
                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
            };
        }
    }

    把多个 version 放 1 个 controller 会和 swagger 打架哦 (因为 swagger 不允许 action same path), 虽然很方便但是我觉得可能不顺风水哦.

    请求 v1.0 就会执行 Get_v1, v2.0 就是 Get_v2

    header response 都会表示 api-supported-versions 和 api-deprecated-versions (如果有).

    如果都没有 deprecated, 会这样

    2. 1 个 controller 一个 version

    通过 namespace 来区分 version, 或者通过 controller 不同名字来做 version 也是可以的. 

    namespace WebApiVersioning.Controllers.v1
    {
        [ApiController]
        [ApiVersion("1.0")]
        [Route("api/v{version:apiVersion}/[controller]")]
        public class WeatherForecastController : ControllerBase
        {
            [HttpGet(Name = "GetWeatherForecast")] 
            public IEnumerable<WeatherForecast> Get()
            {
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                })
                .ToArray();
            }
            private static readonly string[] Summaries = new[]
            {
                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
            };
        }
    }
    namespace WebApiVersioning.Controllers.v2
    {
        [ApiController]
        [ApiVersion("2.0")]
        [Route("api/v{version:apiVersion}/[controller]")]
        public class WeatherForecastController : ControllerBase
        {
            [HttpGet(Name = "GetWeatherForecast")]
            public IEnumerable<WeatherForecast> Get()
            {
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                })
                .ToArray();
            }
          
            private static readonly string[] Summaries = new[]
            {
                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
            };
        }
    }

    Non-version

    有些 API 不需要 version control 的话, 用这个 attribute 就可以了

    [ApiVersionNeutral]
  • 相关阅读:
    密码学浅析
    FireWall Mark + LVS
    tcp/ip首部
    iptables(二)网络防火墙
    BIND服务
    LVS(一)
    QQ、微信消息轰炸
    LVS四种模型(二)
    安装和克隆
    压缩和打包
  • 原文地址:https://www.cnblogs.com/keatkeat/p/15458269.html
Copyright © 2020-2023  润新知