zoukankan      html  css  js  c++  java
  • .Net Core中的Api版本控制

    原文链接:API Versioning in .Net Core
    作者:Neel Bhatt

    简介

    Api的版本控制是Api开发中经常遇到的问题, 在大部分中大型项目都需要使用到Api的版本控制

    在本篇博客中,我们将说明一下如何在.Net Core Api项目中使用Api版本控制。

    本篇博客中测试项目的开发环境:

    • Visual Studio 2017
    • .Net Core 2.1 SDK

    .Net Core Api中使用Api版本控制

    创建一个Api项目

    首先我们创建一个.NET Core Api项目

    使用Nuget安装Api版本控制库

    .NET Core Mvc中,微软官方提供了一个可用的Api版本控制库Microsoft.AspNetCore.Mvc.Versioning。 这里我们可以使用Nuget安装这个包。

    PM> Install-Package Microsoft.AspNetCore.Mvc.Versioning

    修改Startup类

    Microsoft.AspNetCore.Mvc.Versioning库安装完成之后,下一步我们来添加Api版本控制服务。

    这里我们需要在Startup类的ConfigureService方法中添加以下代码。

        services.AddApiVersioning(o => {
            o.ReportApiVersions = true;
            o.AssumeDefaultVersionWhenUnspecified = true;
            o.DefaultApiVersion = new ApiVersion(1, 0);
        });
    

    代码解释

    ReportApiVersion 属性是一个布尔类型,如果设置为true, 在Api请求的响应头部,会追加当前Api支持的版本, 例

    Response Header
    api-supported-versions: 1.0
    content-type: application/json; charset=utf-8
    date: Sat, 06 Oct 2018 05:24:21 GMT
    server: Kestrel
    status: 200
    x-powered-by: ASP.NET
    

    AssumeDefaultVersionWhenUnspecified属性是为了标记当客户端没有指定版本号的时候,是否使用默认版本号
    DefaultApiVersion属性即默认版本号

    创建多版本Api

    这里为了测试.Net Core Mvc的Api版本控制库,我们创建如下2个Controller。

    
        [ApiVersion("1.0")]
        [Route("api/values")]
        [ApiController]
        public class ValuesV1Controller : ControllerBase
        {
            [HttpGet]
            public IEnumerable<string> Get()
            {
                return new string[] { "Value1 from Version 1", "value2 from Version 1" };
            }
        }   
    
        [ApiVersion("2.0")]
        [Route("api/values")]
        [ApiController]
        public class ValuesV2Controller : ControllerBase
        {
            [HttpGet]
            public IEnumerable<string> Get()
            {
                return new string[] { "value1 from Version 2", "value2 from Version 2" };
            }
        }
    

    代码解释

    • Value1ControllerValue2Controller使用了一样的路由"/api/values"
    • Value1Controller类头部使用ApiVersion特性标记了当前Controller的Api版本号是1.0
    • Value2Controller类头部使用ApiVersion特性标记了当前Controller的Api版本号是2.0
      -Value1ControllerValue2Controller都持有相同方法签名的Get方法, 只是2个Get中返回了不同的字符串

    现在我们启动项目,得到的结果如下,说明当没有指定Api版本号时,项目自动使用1.0版本的Api, 即ValuesV1Controller中的Get方法。

    如何在查询字符串(Query String)中使用版本控制

    Microsoft.AspNetCore.Mvc.Versioning支持以QueryString的形式指定请求Api的版本号。开发人员可以在Url中指定api-version参数来选择调用的Api版本号。

    以当前项目为例
    当请求https://localhost:44319/api/values?api-version=2.0时, 返回结果

    ["value1 from Version 2","value2 from Version 2"]
    

    当请求https://localhost:44319/api/values?api-version=1.0时, 返回结果

    ["Value1 from Version 1","value2 from Version 1"]
    

    如何使用路由约束中指定请求Api的版本

    Microsoft.AspNetCore.Mvc.Versioning还支持使用路由约束指定请求Api的版本号。

    例: [Route(“api/{v:apiVersion}/Values”)]

    我们对之前2个Controller的代码作如下修改。

        [ApiVersion("1.0")]
        [Route("api/{v:apiVersion}/values")]
        [ApiController]
        public class ValuesV1Controller : ControllerBase
        {
            [HttpGet]
            public IEnumerable<string> Get()
            {
                return new string[] { "Value1 from Version 1", "value2 from Version 1" };
            }
        }   
    
        [ApiVersion("2.0")]
        [Route("api/{v:apiVersion}/values")]
        [ApiController]
        public class ValuesV2Controller : ControllerBase
        {
            [HttpGet]
            public IEnumerable<string> Get()
            {
                return new string[] { "value1 from Version 2", "value2 from Version 2" };
            }
        }
    
    

    现在我们通过以下2个Url请求Api, 返回的结果如下 :
    /api/2.0/values

    ["value1 from Version 2","value2 from Version 2"]
    

    /api/1.0/values

    ["Value1 from Version 1","value2 from Version 1"]
    

    如何在请求头(HTTP Header)中使用版本控制

    以上的2种方式需要修改请求的Url, 如果你不喜欢这2种方式,Microsoft.AspNetCore.Mvc.Versioning还提供了第三种指定Api版本号的方式,即在HTTP请求头中添加版本号参数。

    为了启用这种方式,我们首先需要在Startup.cs中修改Microsoft.AspNetCore.Mvc.Versioning的配置, 代码如下:

        services.AddApiVersioning(o =>
        {
            o.ReportApiVersions = true;
            o.AssumeDefaultVersionWhenUnspecified = true;
            o.DefaultApiVersion = new ApiVersion(1, 0);
            o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
        });
    

    这里通过ApiVersionReader属性指定了Api版本号是从请求头部的x-api-version属性来的。

    Tips: 一旦你使用o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");, 在查询字符串中指定版本号的方式将不再可用,如果你希望同时支持2种方式,请改用o.ApiVersionReader = ApiVersionReader.Combine(new QueryStringApiVersionReader(), new HeaderApiVersionReader() { HeaderNames = { "x-api-version" }});(多谢seamaswang的更正)

    下面我们通过Postman来请求2.0的Api, 结果正确返回了。

    其他特性

    弃用Api(Deprecated)特性

    有些时候,我们需要标记一些过时的Api为弃用状态,但是我们又不希望完全移除这个版本的Api, 我们可以使用Deprecated特性。

    例:我们当前希望弃用ValuesV1Controller, 我们可以指定Deprecated特性的值为true

        [ApiVersion("1.0", Deprecated = true)]
        [Route("api/values")]
        [ApiController]
        public class ValuesV1Controller : ControllerBase
        {
            [HttpGet]
            public IEnumerable<string> Get()
            {
                return new string[] { "Value1 from Version 1", "value2 from Version 1" };
            }
        }
    
    

    当我们请求在此请求这个api的时候, 在响应头中会出现api-deprecated-versionsapi-supported-versions2个属性。

    Response Header
    api-deprecated-versions: 1.0
    api-supported-versions: 2.0
    content-type: application/json; charset=utf-8
    date: Sat, 06 Oct 2018 06:32:18 GMT
    server: Kestrel
    status: 200
    x-powered-by: ASP.NET
    
    

    这段响应的意思就是1.0版本的Api已经过期了,2.0版本中有相同的Api, 可以换用2.0版本的Api。

    使用ApiVersionNeutral指定不需要版本控制的Api

    在编写Api的时候,对于一些非常简单的Api, 我们可能不需要指定Api版本号, 例如健康检查Api。我们可以使用ApiVersionNeutral特性,将它从Api版本控制中排除掉。

    例:

        [ApiVersionNeutral]
        [Route("api/[controller]")]
        [ApiController]
        public class HealthCheckController : ControllerBase
        {
            public string Get()
            {
                return "Good";
            }
        }
    
    

    本篇源代码

  • 相关阅读:
    内存之RAM、SRAM、DRAM、ROM、FLASH、SDRAM、DDR*
    音频接口之AUX、TRS、RCA、SLR、AES/EBU、S/PDIF
    视频接口之AV、S端子、VGA、DVI、HDMI、DP
    选购硬盘HDD、SSD、SSHD、IDE、SATA、SCSI、SAS、PCIe、M.2、USB
    浅析C#中的“==”和Equals
    编写更好的C#代码
    C# 文件下载四方法
    Linq之Lambda表达式初步认识
    .NET逻辑分层架构总结
    理解 .NET 2015
  • 原文地址:https://www.cnblogs.com/lwqlun/p/9747180.html
Copyright © 2011-2022 走看看