利用Swashbuckle生成Web API Help Pages

利用Swashbuckle生成Web API Help Pages

这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢?

原因如下:

  • 官方文档涉及的内容相当全面,属于那种大而全的知识仓库,不太适合初学者,很容易让人失去重要,让人掉入到具体的细节之中。
  • 对于大多数人来讲开发语言只是工具,程序员都有一个通病,就是死磕工具,把工具学深。我认为在工具上没有必要投入太多时间,以能高效地完成日常的工作项目为准即可。要需求驱动学习,你需要什么学什么。如果你学的新技术新特性只是屠龙之技或者只需要用到的时候去查一下即可的话,这种死磕这又有什么用。没有必要花120%的时间去学100%的知识,你只需要花20%的时间去学习80%的知识就可以了,剩下的等实际的项目中用到的时候去查就可以了,工具只是工具,不是工作本身。
  • 目前基本所有的文章都是基于Windows平台的Visual Studio IDE来介绍的。而我用的是一台Mac,所以我将基于Mac平台的Visual Studio Code讲解适合我们实际项目中遇到的知识。
  • 还有一点,就是这是我个人的学习总结。

这系列文章就是让你去花20%的时间去学80%的东西,剩下的20%再去看官方文档。

本文将通过Swagger的.NET Core的实现封装工具Swashbuckle�来生成上一篇-《创建ASP.NET Core Web API》的帮助文档。

Swashbuckle简介

Swashbuckle有两个核心组件:

  • Swashbuckle.SwaggerGen: 提供生成描述对象,方法,返回类型等JSON Swagger文档的功能。
  • Swashbuckle.SwaggerUI: 一个Swagger UI工具的嵌入式版本,可以使用上面的文档来创建可定制化的Web API的功能描述,包含内置的公共方法的测试�工具。

在middleware中添加并配置Swagger

首先,要将Swashbuckle添加到项目中的project.json

"Swashbuckle": "6.0.0-beta902"

然后在Configure方法中添加SwaggerGen到services集合中,接着在ConfigureServices方法中,允许中间件(middleware)为生成的JSON文档和SwaggerUI提供服务。

执行dotnet run命令,并导航到http://localhost:5000/swagger/v1/swagger.json 查看描述终结点的文档。

{
  "swagger": "2.0",
  "info": {
    "version": "v1",
    "title": "API V1"
  },
  "basePath": "/",
  "paths": {
    "/api/User": {
      "get": {
        "tags": [
          "User"
        ],
        "operationId": "ApiUserGet",
        "consumes": [],
        "produces": [
          "text/plain",
          "application/json",
          "text/json"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/UserItem"
              }
            }
          }
        },
        "deprecated": false
      },
      "post": {
        "tags": [
          "User"
        ],
        "operationId": "ApiUserPost",
        "consumes": [
          "application/json",
          "text/json",
          "application/json-patch+json"
        ],
        "produces": [],
        "parameters": [
          {
            "name": "item",
            "in": "body",
            "required": false,
            "schema": {
              "$ref": "#/definitions/UserItem"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      }
    },
    "/api/User/{id}": {
      "get": {
        "tags": [
          "User"
        ],
        "operationId": "ApiUserByIdGet",
        "consumes": [],
        "produces": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      },
      "put": {
        "tags": [
          "User"
        ],
        "operationId": "ApiUserByIdPut",
        "consumes": [
          "application/json",
          "text/json",
          "application/json-patch+json"
        ],
        "produces": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "item",
            "in": "body",
            "required": false,
            "schema": {
              "$ref": "#/definitions/UserItem"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      },
      "delete": {
        "tags": [
          "User"
        ],
        "operationId": "ApiUserByIdDelete",
        "consumes": [],
        "produces": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      },
      "patch": {
        "tags": [
          "User"
        ],
        "operationId": "ApiUserByIdPatch",
        "consumes": [
          "application/json",
          "text/json",
          "application/json-patch+json"
        ],
        "produces": [],
        "parameters": [
          {
            "name": "item",
            "in": "body",
            "required": false,
            "schema": {
              "$ref": "#/definitions/UserItem"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      }
    },
    "/api/Values": {
      "get": {
        "tags": [
          "Values"
        ],
        "operationId": "ApiValuesGet",
        "consumes": [],
        "produces": [
          "text/plain",
          "application/json",
          "text/json"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        },
        "deprecated": false
      },
      "post": {
        "tags": [
          "Values"
        ],
        "operationId": "ApiValuesPost",
        "consumes": [
          "application/json",
          "text/json",
          "application/json-patch+json"
        ],
        "produces": [],
        "parameters": [
          {
            "name": "value",
            "in": "body",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      }
    },
    "/api/Values/{id}": {
      "get": {
        "tags": [
          "Values"
        ],
        "operationId": "ApiValuesByIdGet",
        "consumes": [],
        "produces": [
          "text/plain",
          "application/json",
          "text/json"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "integer",
            "format": "int32"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "string"
            }
          }
        },
        "deprecated": false
      },
      "put": {
        "tags": [
          "Values"
        ],
        "operationId": "ApiValuesByIdPut",
        "consumes": [
          "application/json",
          "text/json",
          "application/json-patch+json"
        ],
        "produces": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "integer",
            "format": "int32"
          },
          {
            "name": "value",
            "in": "body",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      },
      "delete": {
        "tags": [
          "Values"
        ],
        "operationId": "ApiValuesByIdDelete",
        "consumes": [],
        "produces": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "integer",
            "format": "int32"
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      }
    }
  },
  "definitions": {
    "UserItem": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "age": {
          "format": "int32",
          "type": "integer"
        }
      }
    }
  },
  "securityDefinitions": {}
}

该文档用来驱动Swagger UI,可以导航http://localhost:5000/swagger/ui来查看Swagger UI。

UserController里面的每个方法都可以在该页面上通过点击"Try it out!"进行测试。

定制&扩展

API描述信息

ConfigureSwaggerGen方法可以用来添加作者、版权、描述等信息。

services.ConfigureSwaggerGen(options =>
{
    options.SingleApiVersion(new Info
    {
        Version = "v1",
        Title = "User Web API",
        Description = "ASP.NET Core Web API",
        TermsOfService = "None",
        Contact = new Contact { Name = "Charlie Chu", Email = "charlie.thinker@aliyun.com", Url = "http://zhuchenglin.me/" },
        License = new License { Name = "The MIT License", Url = "http://zhuchenglin.me/" }
    });
});

XML注释

通过在project.json添加“xmlDoc”: true来启用XML注释。

ApplicationBasePath获取该应用的根路径,它必须为XML注释设置一个完整的路径,生成的XML注释名称基于你的应用程序的名称。

注意这个界面是通过之前生成的JSON文件来驱动的,所有的这些API描述信息和XML注释都会写入到这个文件中。

个人博客

我的个人博客

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

推荐阅读更多精彩内容