基于dotNET 5 MVC经典模式引入Swagger进行web api开发和管理发布OAS3标准接口文档全过程


title: 基于dotNET 5 MVC经典模式引入Swagger进行web api开发和管理发布OAS3标准接口文档全过程
date: 2021-06-24
sidebarDepth: 2
tags:

  • dotNET5
  • MVC
  • swagger
  • OAS3
    categories:
  • cms
  • 微软技术
  • 安全

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无需访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。

面向web api开发

大家在开发完 webapi 后,经常为了方便接口双方对接,需要将 webapi 接口文档化,那有没有什么快捷可交互的文档呢?可以利用快捷工具 Swagger,它的可视化 UI 可轻松助你 API 文档化的同时还方便测试 API。

Swashbuckle 就是一个用于生成 Swagger 文档的开源工具包,这篇文章将会讨论如何利用 Swashbuckle 来为你的 Restful API 生成可交互的文档。

什么是Swagger

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无需访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。

Swagger 的优势

  • 支持 API 自动生成同步的在线文档:使用 Swagger 后者可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。
  • 提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。

说白了就是一种接口文档,而且支持在线调试,从而提升web api开发的效率。
其它同类型的工具还有apidoc,如:https://code.z01.com/apidoc/ 就是用apidoc生成,可以检索、遍历,缺点是不能调试。
来自Java开源社区的Swagger则功能更加强大,自然受人欢迎。

一句话:
*** dotNET CORE Swagger的使用,写好注释就是写好接口文档***

其运界面如下所示:


图片名称

什么是OAS3

作为一个经常要提供给API文档给内部和第三方的阅读的“苦程”,我一直在寻找一个完美的Spring MVC文档解决方案。过去,我一直使用的是springfox-swagger2依赖,使用swagger2注解,对代码进行注释,生成swagger文档。 不过,早在2020年Swagger2就已过时,springfox-swagger2也已停止维护。业界普遍转向了OAS3 规范管理文档接口,这也是当前OpenApi规范标准。

在dotNet Core和dotNET 5的web api项目中引入Swagger

注意:这里是web api 项目,在vs 2019中创建项目如下:


图片名称

1、新建一个asp.net core web api项目

图片名称

图片名称

2、Nuget安装Swagger

图片名称

3、为接口及接口中用到的类添加注释

图片名称

图片名称

4、右键项目属性(如果项目中有其他库的,都需要参照配置下)生成XML文档,如下图打勾保存

图片名称

5、Startup配置Swagger,这里用到了一个自定义的扩展类:

SwaggerHttpHeaderOperation,这个类里面增加了调试的Http请求header参数,比如Token就可以扩展下,这样在调试时就可以填写该参数,方便调试需要鉴权的接口。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.IO;
using System.Text;

namespace ZQSwaggerDemo
{
    public class Startup
    {
        const string PROJECTNAME = "知擎物联API";
        const string VERSION = "v1.0.0";

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            //配置swagger
            StringBuilder fDescription = new StringBuilder();
            fDescription.Append("<a target='_blank' href='https://www.yyzq.net' class='link'>常州知擎物联科技有限公司 版权所有</a>");
            fDescription.Append($"<br>API适用标注说明:");
            fDescription.Append($"<br><span style='color:blue'>【NOTOKEN】</span>:无需登录可访问");
            services.AddSwaggerGen(c =>
            {
                c.OperationFilter<SwaggerHttpHeaderOperation>();

                c.SwaggerDoc(VERSION, new Microsoft.OpenApi.Models.OpenApiInfo()
                {
                    Title = PROJECTNAME,
                    Version = VERSION,
                    Description = ""
                }); ;
                //加载注释xml文件(这里演示的代码是为了方便一次性加载多个XML文档,省去了一个个XML文件添加的繁琐)
                string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "ZQ*.xml");
                foreach (string item in files)
                {
                    c.IncludeXmlComments(item);
                }
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseSwagger();//启用中间件服务生成Swagger作为JSON终结点
            app.UseSwaggerUI(c =>
            {
                //启用中间件服务对swagger-ui,指定Swagger JSON终结点
                c.SwaggerEndpoint($"/swagger/{VERSION}/swagger.json", PROJECTNAME);
            });
            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace ZQSwaggerDemo
{
    /// <summary>
    /// Swagger调试header
    /// </summary>
    public class SwaggerHttpHeaderOperation : IOperationFilter
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="context"></param>
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            operation.Parameters.Add(new OpenApiParameter()
            {
                Name = "Token",
                In = ParameterLocation.Header,
                Required = false,
                Schema = new OpenApiSchema { Type = "string" }
            });
        }
    }
}

6、启动项目,访问:

http://localhost:45039/swagger/index.html 可以看到之前写的注释都在文档中体现了出来

图片名称

7、调试接口

对想要调试的接口,展开接口后,点击Try it out按钮,这里我们可以看到之前扩展的Header部分参数(本DEMO仅示范,并未使用,实际项目中还是经常需要自定义一些header参数),填写好参数后,点击Execute调用接口,可以看到成功返回了数据。

图片名称

图片名称

在dotNet Core和dotNET 5的MVC项目中引入Swagger

上面的一节,我们介绍了在web api项目中引入swagger,但大多数项目不是web api项目,而是经典的mvc项目,要如何应用呢?
别急,这里开始分享全过程。

一.新建项目: dotnet new mvc -n SwaggerTest

图片名称

二.添加nuget引用 :dotnet add TodoApi.csproj package Swashbuckle.AspNetCore -v 5.0.0

也可以使用 Package Manager Console

图片名称

三.Startup中的ConfigureServices 添加服务

services.AddSwaggerGen(c =>
          {
              c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Docs", Version = "V1" });
          });

图片名称

四.在Startup中的Configure使用 代码如下

app.UseSwagger();
app.UseSwaggerUI(c=>c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"));

图片名称

五.在HomeController添加如下代码

public class HomeController : Controller
{
    /// <param name="name"></param>        
    [HttpPost("{name}")]
    public IActionResult Find(string name)
    {
        if (string.IsNullOrWhiteSpace(name)) return NotFound();
        else return Content(name);
    }
}

六.测试

图片名称

图片名称

如果上面文档不足,还要可以补充看下面的:

安装 Swagger 中间件

要想利用 Swagger 文档化,需要 nuget 引用 Swashbuckle.AspNetCore 包,还可以通过 Visual Studio 2019 的 NuGet package manager 可视化界面安装 或者 通过 NuGet package manager 命令行工具输入以下命令:

dotnet add package Swashbuckle.AspNetCore

配置 Swagger 中间件

为了配置 Swagger,在 Startup.ConfigureServices 方法中添加如下代码,注意下面的 AddSwaggerGen 方法是用于给 API 文档 添加一些元数据。


  services.AddSwaggerGen(c =>;
  {
      c.SwaggerDoc("v1", new Info
      {
          Version = "v1",
          Title = "Swagger Demo",
          Description = "Swagger Demo for ValuesController",
          TermsOfService = "None",
          Contact = new Contact() { Name = "Joydip Kanjilal",
          Email = "joydipkanjilal@yahoo.com",
          Url = "www.google.com" }
      });
  });

接下来就要启动 Swagger了,在 Startup.Configure 方法下添加如下代码:

  app.UseSwagger();
  app.UseSwaggerUI(c =&gt;
  {
      c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
  });

为了完整性,下面是 Startup 中的所有代码清单。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;
namespace IDGSwaggerDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion
            (CompatibilityVersion.Version_2_2);   
            services.AddSwaggerGen(c =&gt;
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "Swagger Demo",
                    Description = "Swagger Demo for ValuesController",
                    TermsOfService = "None",
                    Contact = new Contact() { Name = "Joydip Kanjilal",
                    Email = "joydipkanjilal@yahoo.com",
                    Url = "www.google.com"
                }
                });
            });
        }
        public void Configure(IApplicationBuilder app,
       IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseMvc();
            app.UseSwagger();
            app.UseSwaggerUI(c =&gt;
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
            });
        }
    }
}

浏览 Swagger UI

现在我们运行一下应用程序来浏览一下 Swagger UI 地址,可以看到 UI 界面如下图所示,图中不同的 Http 请求使用了不同的颜色进行标识,你甚至可以在UI上直接测试不同的 api 接口。

图片名称

在 Action 方法上创建xml注解

到目前为止一切顺利,在刚才生成的 swagger 文档中,并没有看到 5 个 api 接口的任何注解,这就不优雅了,如果想要在 swagger 文档上增加 xml 注解,简单粗暴的做法可以直接在 Controller.Action 顶部写上注解信息。

接下来在 ValuesController 下的每一个 Action 上都加上注解,下面就是修改后的 ValueController。

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        /// 
        /// Get action method without any argument
        /// 
        /// 
        [HttpGet]
        public ActionResult&gt; Get()
        {
            return new string[] { "value1", "value2" };
        }

        /// 
        /// Get action method that accepts an integer as an argument
        /// 
        /// 
        /// 
        [HttpGet("{id}")]
        public ActionResult Get(int id)
        {
            return "value";
        }

        /// 
        /// Post action method to add data
        /// 
        /// 
        [HttpPost]
        public void Post([FromBody] string value)
        {
        }

        /// 
        /// Put action method to modify data
        /// 
        /// 
        /// 
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] string value)
        {
        }

        /// 
        /// Delete action method
        /// 
        /// 
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }

打开 xml 注解

值得注意的是: Swagger 默认并不会显示 XML 注解,需要手工打开它,那怎么做呢?右键 Project,选择 Properties 后切换到 Build 页面,然后选中 XML documentation file 项 并且指定好 xml 生成的位置,参考如下:

图片名称

接下来还要在 ConfigureServices 方法下将生成xml 的路径配置到 swagger 中,如下代码所示:

c.IncludeXmlComments(@"D:\Projects\IDG\IDGSwaggerDemo\IDGSwaggerDemo\IDGSwaggerDemo.xml");

这就是打开 Swagger 中的 xml 注解 所需的所有事情。

指定启动url 到 Swagger UI

要想将启动项目的url指到 SwaggerUI,右键 Project 并选择 Properties,在 Debug 的 Lanuch browser 上指定 swagger 即可,如下图所示:

图片名称

再次运行程序可以发现默认页就是 Swagger URL 了,如下图所示:

图片名称

从图中可以看到,5个API方法后面都有相应的 xml 注解了。

Swashbuckle 是一个非常好的工具,可以简单粗暴的给 API接口生成文档,从文中也可以看出 Swashbuckle 的配置非常简单,Swagger 还有一些更高级的功能,比如通过 CSS 来定制 Swagger UI,还可以根据API的版本生成不同的 Swagger 文

注解格式

寻找[Route(代码,定义为[HttpGet][HttpPost]

/// <summary>
/// 全局错误提示
/// </summary>
/// <remarks>用于系统的错误页提示返回信息。</remarks>
/// <returns>成功返回!</returns>
/// <param name="code">错误代码</param>
/// <returns></returns>
[Route("Common/Error/{code}")]
[HttpGet]
public IActionResult Error(int code)
{
    //int code = DataConvert.CLng(GetParam("code"));
    ViewBag.statusCode = code;
    return View("~/Views/Shared/Prompt/statusCode.cshtml");
}
图片名称

图片名称

相关资料

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容