如何實現 ASP.NET Core WebApi 的版本化

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<WeatherForecast> 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<WeatherForecastController> _logger;

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

        [HttpGet]
        public IEnumerable<WeatherForecast> 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<WeatherForecastController> _logger;

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

        [HttpGet]
        public IEnumerable<WeatherForecast> 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<WeatherForecast> 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<WeatherForecast> 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


本文分享自微信公衆號 - 一線碼農聊技術(dotnetfly)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章