如何实现 ASP.NET Core WebApi 的版本化

DotNetCore实战

共 6416字,需浏览 13分钟

 ·

2021-01-06 20:56


Web API 的版本化可以尽量保证在相同url情况下保留一个 api 的多个版本,通常一个 webapi 会有多个client,这些client包括:app,web,html5,crawl 等等同构或者异构的平台,当 api 升级之后,往往升级前的 api 也得保留,当维护两个api的时候就是一个不小的挑战,毕竟还是存在一些 client 用户需要访问老的api,这时候就需要将 webapi 版本化。

安装 Versioning 包

要想使用 webapi 的版本化功能,需要用 nuget 引用 Microsoft.AspNetCore.Mvc.Versioning 包,还可以通过 Visual Studio 2019 的 NuGet package manager 可视化界面安装 或者 通过 NuGet package manager 命令行工具输入以下命令:


dotnet add package Microsoft.AspNetCore.Mvc.Versioning

启动 API 版本化

当包成功添加到项目之后,接下来就可以在 Startup.ConfigureServices 中将 ApiVersioning 注入到容器中,如下代码所示:


    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddApiVersioning();
        }
    }

在调用 AddApiVersioning() 的时候记得 using Microsoft.AspNetCore.Mvc.Versioning,除了这个默认方法,还可以做一些全局配置,如下代码所示:


    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddApiVersioning(v =>
            {
                v.ReportApiVersions = true;
                v.AssumeDefaultVersionWhenUnspecified = true;
                v.DefaultApiVersion = new ApiVersion(10);
            });
        }
    }

使用 QueryString 指定版本号

先来看一下代码,考虑如下的 api。


    [ApiController]
    [ApiVersion("2.0")]
    [Route("api/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"
        };

        [HttpGet]
        public IEnumerable Get()
        {
            var rng = new Random();
            return Enumerable.Range(15).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-2055),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

从代码中可以看到,我在 WeatherForecastController 上标记了该 Controller 是 v2.0 版本,接下来如何访问呢?可以通过如下链接: http://localhost:61582/api/weatherforecast?api-version=2.0

看到这里,有些朋友就有疑问了,v2.0 的 Get 是有了,那 v1.0 的 Get 怎么访问呢?实际开发中的做法是这样的,会用两个命名空间来表示相应的版本号,可以看如下代码:


namespace WebApplication6.Controllers.v1
{
    [ApiController]
    [ApiVersion("1.0")]
    [Route("api/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"
        };

        private readonly ILogger _logger;

        public WeatherForecastController(ILogger logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable Get()
        {
            var rng = new Random();
            return Enumerable.Range(15).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-2055),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}


namespace WebApplication6.Controllers.v2
{
    [ApiController]
    [ApiVersion("2.0")]
    [Route("api/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"
        };

        private readonly ILogger _logger;

        public WeatherForecastController(ILogger logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable Get()
        {
            var rng = new Random();
            return Enumerable.Range(15).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-2055),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

从上面代码可以看到 WebApplication6.Controllers.v1 表示版本 v1.0 , WebApplication6.Controllers.v2 表示版本 v2.0,接下来依次浏览这两个url。

使用 routes 指定版本号

很显然使用 QueryString 的方式不是很优雅也不符合 Restful 规范,接下来看一下如何通过 Route 改造,考虑下面的类,请注意我是如何在 route 中进行版本化的。


    [ApiController]
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"
        };

        [HttpGet]
        public IEnumerable Get()
        {
            var rng = new Random();
            return Enumerable.Range(15).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-2055),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

在这里,我将 [Route("api/[controller]")] 替换成了 [Route("api/v{version:apiVersion}/[controller]")],接下来将项目跑起来,如下图所示:

忽略 API 版本

在 API 版本化时,有些 API 可能只有一个版本的需求,这时候可以使用 ApiVersionNeutral 特性来忽视版本化,如下代码所示:


    [ApiVersionNeutral]
    [Route("api/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"
        };

        [HttpGet]
        public IEnumerable Get()
        {
            var rng = new Random();
            return Enumerable.Range(15).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-2055),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

译文链接:https://www.infoworld.com/article/3433156/advanced-versioning-in-aspnet-core-web-api.html


往期精彩回顾




【推荐】.NET Core开发实战视频课程 ★★★

.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划

【.NET Core微服务实战-统一身份认证】开篇及目录索引

Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南)

.NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了

10个小技巧助您写出高性能的ASP.NET Core代码

用abp vNext快速开发Quartz.NET定时任务管理界面

在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度

现身说法:实际业务出发分析百亿数据量下的多表查询优化

关于C#异步编程你应该了解的几点建议

C#异步编程看这篇就够了


浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报