ASP.NET Core 实战:构建带有版本控制的 API 接口

 一、前言

  在上一篇的文章中,主要是搭建了我们的开发环境,同时创建了我们的项目模板框架。在整个前后端分离的项目中,后端的 API 接口至关重要,它是前端与后端之间进行沟通的媒介,如何构建一个 “好用” 的 API 接口,是需要我们后端人员好好思考的。
  在系统迭代的整个过程中,不可避免的会添加新的资源,或是修改现有的资源,后端接口作为暴露给外界的服务,变动的越小,对服务的使用方造成的印象就越小,因此,如何对我们的 API 接口进行合适的版本控制,我们势必需要首先考虑。

  系列目录地址:ASP.NET Core 项目实战
  仓储地址:https://github.com/Lanesra712/Grapefruit.VuCore

 二、Step by Step

  项目总是在不断迭代的,某些时候,因为业务发展的需要,需要将现有的接口进行升级,而原有的接口却不能立刻停止使用。比如说,你开发了一个接口提供给爱啪啪 1.0 版本使用,后来爱啪啪的版本迭代了,需要接口返回的数据与原先 1.0 版本返回的数据不同了,这时候,接口肯定是需要升级的,可是如果直接升级原有的接口,还在使用 1.0 版本的用户不就 GG 了,因此,如何做到既可以让 1.0 版本的用户使用,也可以让 2.0 版本的用户使用就需要好好考虑了,常见的解决方案,主要有以下几种。

  a)使用不同的 API 名称

  最简单粗暴,需要变更接口逻辑时就重新起个 API 名称,新的版本调用新的 API 名称,旧的版本调用旧的 API 名称。

https://yuiter.com/api/Secret/Login ##爱啪啪 1.0
https://yuiter.com/api/Secret/NewLogin ##爱啪啪 2.0

  b)在 Url 中标明版本号

  直接将 API 版本信息添加到请求的 Url 中,调用不同版本的 API ,就在 URL 中直接标明使用的是哪个版本。

https://yuiter.com/api/v1/Secret/Login ##爱啪啪 1.0
https://yuiter.com/api/v2/Secret/Login ##爱啪啪 2.0

  c)请求参数中添加版本信息

  将 API 的版本信息作为请求的一个参数传递,通过指定参数值来确定请求的 API 版本。

https://yuiter.com/api/Secret/Login?version=1 ##爱啪啪 1.0
https://yuiter.com/api/Secret/Login?version=2 ##爱啪啪 2.0

  d)在 header 中标明版本号

  前端在请求 API 接口时,在 header 中添加一个参数用来表明请求的版本信息,后端通过前端在 header 中设置的参数来判断,从而执行不同的业务逻辑分支。

POST https://yuiter.com/api/Secret/Login
Host: yuiter.com
api-version: v1   ##爱啪啪 1.0

POST https://yuiter.com/api/Secret/Login
Host: yuiter.com
api-version: v2   ##爱啪啪 2.0

  在 Grapefruit.VuCore 这个项目中,我选择将 API 的版本信息添加到请求的地址中,从而明确的指出当前请求的接口版本信息。

  1、Swagger 集成

  后端完成了接口之后,肯定需要告诉前端,不管是整理成 txt/excel/markdown 文档,亦或是写完一个接口就直接发微信告诉前端,总是要多做一步的事情,而 Swagger 则可以帮我们省去这一步。通过配置之后,Swagger 就可以根据我们的接口自动生成 API 的接口文档,省时,省力。当然,如果前端小姐姐单身可撩,而你碰巧有意的话,另谈。

  Swagger 是一个可以将接口文档自动生成,同时可以对接口功能进行测试的开源框架,在 ASP.NET Core 环境下,主流的有 Swashbuckle.AspNetCore 和 NSwag 这两个开源框架帮助我们生成 Swagger documents。这里,我采用的是 Swashbuckle.AspNetCore

  在使用 Swashbuckle.AspNetCore 之前,首先我们需要在 API(Grapefruit.WebApi) 项目中添加对于 Swashbuckle.AspNetCore 的引用。你可以直接右键选中 API 项目选择管理 Nuget 程序包进行加载引用,也可以通过程序包管理控制台进行添加引用,这里注意,使用程序包管理控制台时,你需要将默认的项目修改成 API(Grapefruit.WebApi) 项目。当引用添加完成后,我们就可以在项目中配置 Swagger 了。

Install-Package Swashbuckle.AspNetCore

  ASP.NET Core 的本质上可以看成是一个控制台程序,在我们创建好的 ASP.NET Core Web API 项目中,存在着两个类文件:Program.cs 以及 Startup.cs。与控制台应用一样,Program 类中的 Main 方法是整个程序的入口,在这个方法中,我们将配置好的 IWebHostBuilder 对象,构建成 IWebHost 对象,并运行该 IWebHost 对象从而达到运行 Web 项目的作用。

  在框架生成的 Program 类文件中,在配置 IWebHostBuilder 的过程时,框架默认为我们添加了一些服务,当然,这里你可以注释掉默认的写法,去自己创建一个 WebHostBuilder 对象。同时,对于一个 ASP.NET Core 程序来说,Startup 类是必须的(你可以删除生成的 Startup 类,重新创建一个新的类,但是,这个新创建的类必须包含 Configure 方法,之后只需要在 UseStartup<Startup> 中将该类配置为 Startup 类即可),这里如果不指定 Startup 类会导致启动失败。

  在 Startup 类中,存在着 ConfigureServices 和 Configure 这两个方法,在 ConfigureServices 方法中,我们将自定义服务通过依赖注入的方式添加到 IServiceCollection 容器中,而这些容器中的服务,最终都可以在 Configure 方法中进行使用;而 Configure 方法则用于指定 ASP.NET Core 应用程序将如何响应每一个 HTTP 请求,我们可以在这里将我们自己创建的中间件(Middleware)绑定到 IApplicationBuilder 上,从而添加到 HTTP 请求管道中。

  这里只是很粗略的说明了 ASP.NET Core 项目的启动过程,想要仔细了解启动过程的推荐园子里的这篇文章 =》ASP.NET Core 2.0 : 七.一张图看透启动背后的秘密,因为 ASP.NET Core 2.1 版本相比于 2.0 版本又有些改变,这里有一些不一样的地方需要你去注意。

  当我们简单了解了启动过程后,就可以配置我们的 Swagger 了。Swashbuckle.AspNetCore 帮我们构建好了使用 Swagger 的中间件,我们只需要直接使用即可。

  首先我们需要在 ConfigureServices 方法中,将我们的服务添加到 IServiceCollection 容器中,这里,我们需要为生成的 Swagger Document 进行一些配置。

services.AddSwaggerGen(s =>
{
    s.SwaggerDoc("v1", new Info
    {
        Contact = new Contact
        {
            Name = "Danvic Wang",
            Email = "[email protected]",
            Url = "https://yuiter.com"
        },
        Description = "A front-background project build by ASP.NET Core 2.1 and Vue",
        Title = "Grapefruit.VuCore",
        Version = "v1"
    });
});

  之后,我们就可以在 Configure 方法中启用我们的 Swagger 中间件。

app.UseSwagger();
app.UseSwaggerUI(s =>
{
    s.SwaggerEndpoint("/swagger/v1/swagger.json", "Grapefruit.VuCore API V1.0");
});

  此时,当你运行程序,在域名后面输入/swagger 即可访问到我们的 API 文档页面。因为项目启动时默认访问的是我们 api/values 的 GET 请求接口,这里我们可以打开 Properties 下的 launchSetting.json 文件去配置我们的程序默认打开页面。

  从上面的图可以看出,不管是使用 IIS 或是程序自托管,我们默认打开的 Url 都是 api/values,这里我们将两种启动方式的 launchUrl 值都修改成 swagger 之后再次运行我们的项目,可以发现,程序默认的打开页面就会变成我们的 API 文档页面。

  我们使用 API 文档的目的,就是为了让前端知道请求的方法地址是什么,需要传递什么参数,而现在,并没有办法显示出我们对于参数以及方法的注释,通过查看 Swashbuckle.AspNetCore 的 github 首页可以看到,我们可以通过配置,将生成的 json 文件中包含我们对于 Controller or Action 的 Xml 注释内容,从而达到显示注释信息的功能(最终呈现的 Swagger Doc 是根据之前我们定义的这个 “/swagger/v1/swagger.json” json 文件来生成的)。

  右键我们的 API 项目,属性 =》生产,勾选上 XML 文档文件,系统会默认帮我们创建生成 XML 文件的地址,这时候,我们重新生成项目,则会发现,当前项目下会多出这个 XML 文件。在重新生成项目的过程中,你会发现,错误列表会显示很多警告信息,提示我们一些方法没有添加 XML 注释。如果你和我一样强迫症的话,可以把 1591 这个错误添加到上面的禁止显示警告中,这样就可以不再显示这个警告了。

  创建好 XML 的注释文件后,我们就可以配置我们的 Swagger 文档,从而达到显示注释的功能。这里,因为我会在 Grapefruit.Application 类库中创建各种的 Dto 对象,而接口中是会调用到这些 Dto 对象的。因此,为了显示这些 Dto 上的注释信息,这里我们也需要生成 Grapefruit.Application 项目的 XML 注释文件。

  PS:这里我是将每个项目生成的注释信息 xml 文档地址都放在了程序的基础路径下,如果你将 xml 文档生成在别的位置,这里获取 xml 的方法就需要你进行修改。

services.AddSwaggerGen(s =>
{
    //...

    //Add comments description
    //
    var basePath = Path.GetDirectoryName(AppContext.BaseDirectory);//get application located directory
    var apiPath = Path.Combine(basePath, "Grapefruit.WebApi.xml");
    var dtoPath = Path.Combine(basePath, "Grapefruit.Application.xml");
    s.IncludeXmlComments(apiPath, true);
    s.IncludeXmlComments(dtoPath, true);
});

  当我们把 Swagger 配置完成之后,我们就可以创建具有版本控制的 API 接口了。

  2、带有版本控制的 API 接口实现

  在请求的 API Url 中标明版本号,我不知道你第一时间看到这个实现方式,会想到什么,对于我来说,直接在路由信息中添加版本号不就可以了。。。em,这样过于投机取巧了。。。。

[Route("api/v1/[controller]")]//添加版本信息为v1
[ApiController]
public class ValuesController : ControllerBase
{
}

  想了想,在 Url 中添加版本号,这个版本号是不是很像我们在 MVC 中使用的 Area。

  Area 是 MVC 中经常使用到的一个功能,我们通常会将某些小的模块拆分成一个个的 Area,而这一个个的小 Area 其实就是这个 MVC 项目中的 MVC。通过为 controller 和 action 添加另一个路由参数 area,从而达到创建具有层次路由的结构。比如,这里,我们可以创建一个 Area 叫 v1,用来存储我们 1.x 版本的 API 接口,之后如果有新的 API 版本,新增一个 Area 即可,是不是很简单,嗯,说干就干。

  右击我们的 API 项目,选择添加区域,新增的 Area 名称为 v1。

  当 ASP.NET Core 的脚手架程序添加完成 Area 后,则会打开一个文件提示我们需要在 MVC 中间件中创建适用于 Area 的路由定义。

app.UseMvc(routes =>
{
  routes.MapRoute(
    name : "areas",
    template : "{area:exists}/{controller=Home}/{action=Index}/{id?}"
  );
});

  当我们添加好路由规则定义后,我们在 Area 的 Controllers 文件夹下添加一个 WebAPI Controller。不同于 ASP.NET 中的 Area ,当我们在 ASP.NET Core 创建好一个 Area 之后,脚手架生成的文件中不再有 XXXAreaRegistration(XXX 为 Area 的名称)文件去注册这个 Area,而我们只需要在 Area 中的 Controller 中添加 Area 特性,即可告诉系统框架,这个 Controller 是在当前的 Area 下的。

  如果你有自己尝试的话,就会发现,当我们创建好一个 v1 的 Area 后,这个请求的地址并没有按照我们的想法会体现在路由信息中,我们最后还是需要在 Route 中手动指明 API 版本。

[Area("v1")]
[Route("api/v1/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
}

  

  这样的话,和最开始直接在路由信息中写死版本信息其实也就没什么差别了,上网搜了搜,发现巨硬爸爸,也早已为我们准备好了实现版本控制 API 的利器 - Microsoft.AspNetCore.Mvc.Versioning。

  和上面使用 Swashbuckle.AspNetCore 的方式相同,在我们使用 Versioning 之前,需要在我们的 API 项目中添加对于该 dll 的引用。这里需要注意下安装的版本问题,因为 Grapefruit.VuCore 这个框架距离现在搭建也有几个月的时间了,在这个月初的时候 .NET Core 2.2 也已经发布了,如果你和我一样还是采用的 .NET Core 2.1 版本的话,这里安装的 Versioning 版本最高只能到 2.3。

Install-Package Microsoft.AspNetCore.Mvc.Versioning

  当我们安装完成之后,就可以进行配置了。

public void ConfigureServices(IServiceCollection services)
{
    services.AddApiVersioning(o =>
    {
        o.ReportApiVersions = true;//return versions in a response header
        o.DefaultApiVersion = new ApiVersion(1, 0);//default version select
        o.AssumeDefaultVersionWhenUnspecified = true;//if not specifying an api version,show the default version
    });
}

  ReportApiVersions:这个配置是可选的,当我们设置为 true 时,API 会在响应的 header 中返回版本信息。

  DefaultApiVersion:指定在请求中未指明版本时要使用的默认 API 版本。这将默认版本为1.0。

  AssumeDefaultVersionWhenUnspecified:这个配置项将用于在没有指明 API 版本的情况下提供请求,默认情况下,会请求默认版本的 API,例如,这里就会请求 1.0 版本的 API。

  这里,删除我们之前的创建的 Area 和默认的 ValuesController,在 Controllers 文件夹下新增一个 v1 文件夹,将所有 v1 版本的 Controller 都建在这个目录下。新建一个 Controller,添加上 ApiVersion Attribute 指明当前的版本信息。因为我采用的方案是在 Url 中指明 API 版本,所以,我们还需要在 Route 中修改我们的路由属性以对应 API 的版本。这里的 v 只是一个默认的惯例,你也可以不添加。

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class VaulesController : ControllerBase
{
}

  当我们修改好我们的 Controller 之后,运行我们的项目,你会发现,API 文档中显示的请求地址是不对的,难道是我们的配置没起作用吗?通过 Swagger 自带的 API 测试工具测试下我们的接口,原来这里请求的 Url 中已经包含了我们定义的版本信息,当我们指定错误的版本信息时,工具也会告诉我们这个版本的接口不存在。

  虽然我们请求的 Url 中已经带上了版本信息,但是 API 文档上显示的请求地址却是不准确的,强迫症,不能忍。这里,需要我们修改生成 Swagger 文档的配置代码,将路由中的版本信息进行替换。重新运行我们的项目,可以发现,文档显示的 Url 地址也已经正确了,自此,我们创建带有版本控制的 API 也就完成了。

public void ConfigureServices(IServiceCollection services)
{
    services.AddSwaggerGen(s =>
    {
        //...

        //Show the api version in url address
        s.DocInclusionPredicate((version, apiDescription) =>
        {
            var values = apiDescription.RelativePath
                .Split(‘/‘)
                .Select(v => v.Replace("v{version}", version));

            apiDescription.RelativePath = string.Join("/", values);

            return true;
        });
    });
}

 三、总结

  本章使用了 Microsoft.AspNetCore.Mvc.Versioning 这一组件来实现我们对于 API 版本控制的功能实现,可能你会有疑问,我们直接在路由中写明版本信息不是更简单吗?在我看来,使用这一组件的目的,在于我们可以以多种的方式实现 API 版本控制的目的,如果哪天你不想在 Url 中指明版本信息后,你可以很快的使用别的形式来完成 API 的版本控制。另外,直接在路由中写上版本信息,是不是会显得我们比较 ‘low’,哈哈哈,开玩笑,最后祝大家圣诞快乐~~~

原文地址:https://www.cnblogs.com/danvic712/p/10176823.html

时间: 2024-09-28 19:18:31

ASP.NET Core 实战:构建带有版本控制的 API 接口的相关文章

ASP.NET Core 实战:将 .NET Core 2.0 项目升级到 .NET Core 2.1

原文:ASP.NET Core 实战:将 .NET Core 2.0 项目升级到 .NET Core 2.1  一.前言  最近一两个星期,加班,然后回去后弄自己的博客,把自己的电脑从 Windows 10 改到 Ubuntu 18.10 又弄回 Windows 10,原本计划的学习 Vue 中生命周期的相关知识目前也没有任何的进展,嗯,罪过罪过.看了眼时间,11月也快要结束了,准备补上一篇如何将我们的 .NET Core 2.0 版本的程序升级到 .NET Core 2.1 版本,好歹也算多学

ASP.Net Core WebApi几种版本控制对比

原文:ASP.Net Core WebApi几种版本控制对比 一.版本控制的好处: (1)有助于及时推出功能, 而不会破坏现有系统. (2)它还可以帮助为选定的客户提供额外的功能. API 版本控制可以采用不同的方式进行控制,方法如下: (1)在 URL 中追加版本或作为查询字符串参数, (2)通过自定义标头和通过接受标头 在这篇文章中, 让我们来看看如何支持多个版本的 ASP.NET  Core  Web API. 一.创建asp.net core webapi 项目,引用NuGet包:Ins

ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目

 一.前言 这几年前端的发展速度就像坐上了火箭,各种的框架一个接一个的出现,需要学习的东西越来越多,分工也越来越细,作为一个 .NET Web 程序猿,多了解了解行业的发展,让自己扩展出新的技能树,对自己的职业发展还是很有帮助的.毕竟,现在都快到9102年了,如果你还是只会 Web Form,或许还是能找到很多的工作机会,可是,这真的不再适应未来的发展了.如果你准备继续在 .NET 平台下进行开发,适时开始拥抱开源,拥抱 ASP.NET Core,即使,现在工作中可能用不到. 雪崩发生时,没有一

微服务介绍及Asp.net Core实战项目系列之微服务介绍

0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 一.微服务选型 在做微服务架构的技术选型的时候,以"无侵入"和"社区活跃"为主要的考量点,将来升级为原子服务架构.量子服务架构的时候.甚至恢复成单体架构的时候,代价最小. 软件开发只需要组装,不再需要从头开发. 选型可以参考一下张队长的文章:https://mp.weixin.qq.com/s/UIFjm7W6bDfdmjpeMVJtqA 二.微服务架构是什么? 每一个微服务都是一个零件,并使用这

ASP.NET Core 实战:Linux 小白的 .NET Core 部署之路

 一.前言  最近一段时间自己主要的学习计划还是按照毕业后设定的计划,自己一步步的搭建一个前后端分离的 ASP.NET Core 项目,目前也还在继续学习 Vue 中,虽然中间断了很长时间,好歹还是坚持下来了,嗯,看了看时间,原本决定的半年完成肯定是完不成了.这两周重新拾起来学习 Vue,文章也在慢慢的更新中,这一篇文章主要是想提前试试水将 ASP.NET Core 部署到 Linux Server 上,原本的打算是把毕业设计就部署到 Linux 上,最终也未能成行,究其原因,还是自己太懒太拖了

ASP.NET Core 实战:使用 NLog 将日志信息记录到 MongoDB

在项目开发中,日志系统是系统的一个重要组成模块,通过在程序中记录运行日志.错误日志,可以让我们对于系统的运行情况做到很好的掌控.同时,收集日志不仅仅可以用于诊断排查错误,由于日志同样也是大量的数据,通过对这些数据进行集中分析,可以产生极大的价值. 在微服务的系统架构中,由于一个系统会被拆成很多个功能模块,每个模块负责不同的功能,对于日志系统的要求也会更高,比较常见的有 EFLK(ElasticSearch + Filebeat + LogStash + Kibana) 方案,而对于我们这种单体应

ASP.NET Core 实战(一)CURD

我一哥们从公司跳槽,推荐我去华为面试.大家也知道,华为不需要.net程序员,去了还要转java,你要是放到3年前的那次面试,你放我英语四级一马,我还真就去了,现在虽然你不刻意要求英语,可以放宽限制,我也是有心无力,真的是没精力去转什么java.和有些公司就是没有缘分,没办法的事. 今天我们来看一下ASP.NET Core的增删改查Demo.首先我们来看一下项目结构. 大家发现了吧,图标变了,在创建ASP.NET Core项目前,确保你已经安装了VS2015. OK,接下来我们大概看一下项目文件,

第二章 指南(2)用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio 作者:Mike Wasson 和 Rick Anderson 翻译:谢炀(kiler) 校对:何镇汐.

在ASP.NET Core 2.2 中创建 Web API并结合Swagger

一.创建 ASP.NET Core WebApi项目 二.添加 三. ----------------------------------------------------------- 一.创建项目,WideWorldImporters.API,选项按照下列图操作 二.引用需要的Nuget包 Microsoft.EntityFrameworkCore.SqlServer Swashbuckle.AspNetCore Swashbuckle.AspNetCore包允许为Web API启用帮助页