NET8环境中实现API版本控制

1、背景

在实际环境中,常常需要对API进行版本的管理,以免方法修改后造成不可控。网上在介绍.NET环境中常用版本控制的是Microsoft.AspNetCore.Mvc.Versioning包,但改包已经弃用了,因此这次使用它的升级包(还是原作者开发的)Asp.Versioning.Mvc
这是原来的包:
在这里插入图片描述
这是新的包:Asp.Versioning.Mvc
在这里插入图片描述

2、具体实现

2.1、program.cs中的配置

//版本控制
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new Asp.Versioning.ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    // 结合多种版本控制方式
    options.ApiVersionReader = ApiVersionReader.Combine(
        new QueryStringApiVersionReader("version"),   
        new UrlSegmentApiVersionReader(),             
        new HeaderApiVersionReader("X-API-Version"),
        new MediaTypeApiVersionReader("version")
        );
}).AddMvc();

有四种方法的版本控制,都给加上。
new QueryStringApiVersionReader("version"), 是指通过URL中的参数来确认。例如:http://xxxx/getuser?version=1
new UrlSegmentApiVersionReader()是指通过路由进行确认,例如:http://xxxx/api/v1/getuserhttp://xxxx/api/v2/getuser
new HeaderApiVersionReader("X-API-Version")是指通过header头信息来确认。例如,设置header.add("X-API-Version","1")来设置
new MediaTypeApiVersionReader("version")是通过content_type信息来设置。
其中通过路由的设置优先级最高(就是new UrlSegmentApiVersionReader()的优先级最高)。
在这些配置之前,就是设置一些默认值。例如默认的版本是1.0(options.DefaultApiVersion = new Asp.Versioning.ApiVersion(1, 0);)等,运行后就可以通过Swagger进行查看了。

另外,将配置以下AddSwaggerGen,可以查询不同版本的API接口

builder.Services.AddSwaggerGen(options =>
{
    // 为不同版本定义Swagger文档
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "MyAPIv1",
        Description = "API 文档: 版本 1"
    });
    options.SwaggerDoc("v2", new OpenApiInfo
    {
        Version = "v2",
        Title = "MyAPIv2",
        Description = "API 文档: 版本 2"
    });

    // 使用解决冲突的策略
    options.ResolveConflictingActions(apiDescriptions =>
    {
        return apiDescriptions.First();
    });
});

以及为每个版本设置不同的文档

app.UseSwaggerUI(options =>
{
    // 为每个版本定义端点
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPIv1");
    options.SwaggerEndpoint("/swagger/v2/swagger.json", "MyAPIv2");
});

因此完整的program.cs文件配置如下:

using Asp.Versioning;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    // 为不同版本定义Swagger文档
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "MyAPIv1",
        Description = "API 文档: 版本 1"
    });
    options.SwaggerDoc("v2", new OpenApiInfo
    {
        Version = "v2",
        Title = "MyAPIv2",
        Description = "API 文档: 版本 2"
    });

    // 使用解决冲突的策略
    options.ResolveConflictingActions(apiDescriptions =>
    {
        return apiDescriptions.First();
    });

		//添加注释
		var file = Path.Combine(AppContext.BaseDirectory, "SwaggerDoc.xml");  // xml文档绝对路径
		var path = Path.Combine(AppContext.BaseDirectory, file); // xml文档绝对路径
		options.IncludeXmlComments(path, true); // true : 显示控制器层注释
		options.OrderActionsBy(o => o.RelativePath); // 对action的名称进行排序,如果有多个,就可以看见效果了
});

//版本控制
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new Asp.Versioning.ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    // 结合多种版本控制方式
    options.ApiVersionReader = ApiVersionReader.Combine(
        new QueryStringApiVersionReader("version"),
        new UrlSegmentApiVersionReader(),
        new HeaderApiVersionReader("X-API-Version"),
        new MediaTypeApiVersionReader("version")
        );
}).AddMvc();

var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(options =>
    {
        // 为每个版本定义端点
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyAPIv1");
        options.SwaggerEndpoint("/swagger/v2/swagger.json", "MyAPIv2");
    });
}

app.UseHttpsRedirection();
//app.UseStaticFiles();
app.UseAuthorization();
app.MapControllers();
app.Run();

2.2、Controller的设置

为每个controller创建一个不同版本的文件夹,以及相同名称的controller,以及内部相同的方法,如下图所示
在这里插入图片描述
这样,因为空间不同,可以创建两个相同名称的controller
具体代码如下:

namespace APIVersionDemo.Controllers.V2
{
    [ApiVersion(1.0)]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]/[action]")] // URI版本控制
    // 注意:查询字符串、Header和媒体类型版本控制通常不需要额外的路由属性
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "1111", "111", "111", "111", "111", "111", "111", "111", "111", "111"
        };

        private readonly ILogger<WeatherForecastController> _logger;


        /// <summary>
        /// 123123
        /// </summary>
        /// <param name="logger"></param>
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        [MapToApiVersion(1.0)]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

这里面有如下注意事项:1、在action上面的[MapToApiVersion(1.0)],其版本号可以与controller中的不同,甚至是更高也OK。例如。controller上标注了[ApiVersion(1.0)],但方法上面标注了[MapToApiVersion(3.0)]。这个也是可以的。另外一个controller与其代码相同,只是1.0变成了2.0。

2.3 运行效果

在这里插入图片描述

2.3.1 uri访问

在这里插入图片描述
直接访问:http://localhost:5021/api/v1/WeatherForecast/Get,没有任何问题。

2.3.2 通过参数访问

刚才提到了,uri方式的优先级是最高的(就是在controller上面加上的那句[Route("api/v{version:apiVersion}/[controller]/[action]")] ),若想使用其他方式,则必须把controller改为正常的[Route("api/[controller]/[action]")] ,否则就会报如下的错误
在这里插入图片描述
因此,将controller中的route改为正常的。使用参数访问如下:
在这里插入图片描述

2.3.3、使用header访问

在header中添加key-value。其中X-API-Version就是program中自定义设置的
在这里插入图片描述

2.3.4、使用MediaType访问

在这里插入图片描述

3、代码

代码下载地址

4、参考

主要参考了以下资料:
1、.NET 8 中 API 版本控制的最佳实践
2、ASP.NET Core WebAPI 版本控制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值