從壹開始前后端分離【 .NET Core2.0/3.0 +Vue2.0 】框架之四 || Swagger的使用 3.2


本文3.0版本文章

https://mp.weixin.qq.com/s/SHNNQoYF-t8i2j85E1oSYA

 

 

前言

如果想直接在域名的根目錄直接加載 swagger 比如訪問:localhost:8001 就能訪問,可以這樣設置:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
    c.RoutePrefix = "";//路徑配置,設置為空,表示直接訪問該文件,
//路徑配置,設置為空,表示直接在根域名(localhost:8001)訪問該文件,注意localhost:8001/swagger是訪問不到的,
//這個時候去launchSettings.json中把"launchUrl": "swagger/index.html"去掉, 然后直接訪問localhost:8001/index.html即可

});

 

 

書接上文《從零開始搭建自己的前后端分離【 .NET Core2.0 Api + Vue 2.0 】框架之三 || Swagger的使用 3.1》,上文中只是簡單的對如何使用Swagger作了介紹,而且最后也提出了幾個問題,這里再重溫下那幾個問題:

為何直接 F5 運行,首頁還是無法加載?

接口雖有,但是卻沒有相應的文字說明?

項目開發中的實體類是如何在Swagger中展示的?

對於接口是如何加權限驗證的?

 

一、swagger的一般用法

0、設置swagger頁面為首頁——開發環境

在上一回中我們提到,我們直接F5運行項目,出現了系統默認頁,

 


雖然可以在輸入/swagger后,順利的訪問swagger ui頁,但是我們發現每次運行項目,都會默認訪問api/values這個接口,我想要將啟動頁設為swagger(或者是任意一個頁面),你就需要用到了

**設置文件launchSettings.json **了:

 

 

然后你再一次F5 運行,就會發現不一樣了,其他的配置,以及以后部署中的設置,我們會在以后的文章中都有提到。

 

1、設置默認直接首頁訪問 —— 生產環境

上邊的方法很正常,直接這么運行,就可以了,但是如果我們部署到服務器,就會發現,上邊的那種默認啟動首頁無效了,還是需要我們每次手動在域名后邊輸入 /swagger ,麻煩!

別慌,swagger 給我們提供了這個擴展,我們可以指定一個空字符,作為 swagger 的地址,在Configure中配置中間件:

 app.UseSwagger();
 app.UseSwaggerUI(c =>
 { 
     c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"Blog.Core v1");// 將swagger設置成首頁
     c.RoutePrefix = ""; //路徑配置,設置為空,表示直接在根域名(localhost:8001)訪問該文件,注意localhost:8001/swagger是訪問不到的,去launchSettings.json把launchUrl去掉
 });

 

 

 然后再把我們上邊的項目文件 launchSettings.json 的 launchUrl 給去掉就行了,這樣我們無論是本地開發環境,還是生產環境,都可以默認首頁加載了。

比如我的在線地址 :apk.neters.club/

 

2、為接口添加注釋

接下來,我們就需要解決第二個問題,如何增加文字說明,就是傳說中的注釋,我們只需要在需要的api接口方法上,連點三次 / 即可:

 

添加好了注釋,那我們接下來就需要把注釋信息導入到swagger里,需要用到xml文檔,右鍵web 項目名稱=>屬性=>生成,勾選“輸出”下面的“xml文檔文件”,系統會默認生成一個,當然老規矩,你也可以自己起一個名字:

這里我用的是相對路徑,可以直接生成到 api 層的 bin文件夾下:

 

 

有了注釋和文檔,那接下來就是導入了,也是很簡單,只需要一行即可:

 var basePath = AppContext.BaseDirectory;
 var xmlPath = Path.Combine(basePath, "Blog.Core.xml");//這個就是剛剛配置的xml文件名
 c.IncludeXmlComments(xmlPath);

 

運行查看,沒問題!

 

 

3、忽略注釋警告

這個時候,我們看看有沒有錯誤,一看,咦~~~果然,雖然是警告,可以強迫症呀,一看還挺多

 

別慌!一看,哦!原來是swagger把一些 action 方法都通過xml文件配置了,如果你不想每一個方法都這么加注釋,可以這么配置(對當前項目進行配置,可以忽略警告,記得在后邊加上分號 ;1591):

 

 

這時候你可以看看,所有的警告都已經消失不見了。

4、給控制器也添加注釋

剛剛可能你沒太注意,我們上邊只是給方法加了注釋,但是控制器還沒有加上,那怎么辦呢,有一個復雜的方法,就是添加一個過濾器  c.DocumentFilter<ControllerDescriptionFilter>(); ,然后自己添加一個 .Tags ,但是這個麻煩!不多說,官方已經考慮到了這個問題了,很簡單:

首先我們在控制器上加上注釋:

 

 

 

然后配置swagger的 xml 文檔導入方法:

 

 

 當當當,出來了:

 

5、對 Model 也添加注釋說明

接下來開始第三個問題:添加實體類說明注釋

 

新建一個.net core 類庫Blog.Core.Model,注意是 .net core的類庫,或者使用標准庫也是可以的!(標准庫可以在 NetCore 和 Framework 兩個項目都可以跑)

 

 
新建一個Love的實體類
    /// <summary>
    /// 這是愛
    /// </summary>
    public class Love
    {
        /// <summary>
        /// id
        /// </summary>
        public int Id { get; set; }
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
 
這里現在有兩個情況,或者說是兩個操作方案:
 
1、當前 api 層直接引用了 Blog.Core.Model 層;

 

這個時候,我們只需要配置仿照上邊 api 層配置的xml文檔那樣,在 Blog.Core.Model 層的 XML 輸出到 API 層就行了:

 

2、API 層沒有直接引用 Model 層,而是通過級聯的形式;

就比如我的 Github 上的代碼那樣:

 效果和上邊是一樣的,也算是引用 Model 層了。

 

 

6、導入model.xml到swagger,然后api添加參數

配置xml文檔

 public void ConfigureServices(IServiceCollection services)
 {
     services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

     #region Swagger
     services.AddSwaggerGen(c =>
     {
         c.SwaggerDoc("v1", new Info
         {
             Version = "v0.1.0",
             Title = "Blog.Core API",
             Description = "框架說明文檔",
             TermsOfService = "None",
             Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "Blog.Core", Email = "Blog.Core@xxx.com", Url = "https://www.jianshu.com/u/94102b59cc2a" }
         });

         //就是這里
         var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
var basePath2 = AppContext.BaseDirectory;// 這種寫法也是可以的
    
//就是這里 var xmlPath = Path.Combine(basePath, "Blog.Core.xml");//這個就是剛剛配置的xml文件名 c.IncludeXmlComments(xmlPath, true);//默認的第二個參數是false,這個是controller的注釋,記得修改 var xmlModelPath = Path.Combine(basePath, "Blog.Core.Model.xml");//這個就是Model層的xml文件名 c.IncludeXmlComments(xmlModelPath); }); #endregion }

 

 

接口添加注釋

     /// <summary>
       /// post
       /// </summary>
       /// <param name="love">model實體類參數</param>
        [HttpPost]
        public void Post(Love love)
        {
        }

 

dang dang dang,就出來了

 
 

 

7、去掉Swagger警告提示

在Model層中,我們建立了很多實體,如果你沒有為每一個實體都添加注釋的話,可能會出現這樣的警告:

如果有的小伙伴,不想添加注釋,而又不想看到這個強迫症的警告提示,那就可以這么做,

右鍵項目 屬性 -》 Errors and warnings 配置 1591:

 

 

8、隱藏某些接口

如果不想顯示某些接口,直接在controller 上,或者action 上,增加特性

[ApiExplorerSettings(IgnoreApi = true)]

 

 

9、自定義 Swagger Index 靜態頁模板

有時候我們為了在頁面上增加一些小東西,比如說一個圖片或者說,修改部分css樣式,甚至更改 js 事件,那我們就必須修改 index.html 頁面,很簡單:

 

1、首先我們在 api 根目錄下邊創建一個 index.html 頁面,

<!--<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.1.0+c940f0f28d"
        data-version="4.1.0+c940f0f28d" data-path="/profiler/"
        data-current-id="" data-ids="" data-position="Left"
        data-authorized="true" data-max-traces="15" data-toggle-shortcut="Alt+P"
        data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
</script>-->

<!--1、版本號要與nuget包一致;2、id不能為空-->
<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.1.0+c940f0f28d"
        data-version="4.1.0+c940f0f28d" data-path="/profiler/"
        data-current-id="4ec7c742-49d4-4eaf-8281-3c1e0efa8888" data-ids="4ec7c742-49d4-4eaf-8281-3c1e0efa8888"
        data-position="Left"
        data-authorized="true" data-max-traces="5" data-toggle-shortcut="Alt+P"
        data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
</script>

<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>%(DocumentTitle)</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="./swagger-ui.css">
    <link rel="icon" type="image/png" href="./logo/favicon-32x32.png" sizes="32x32" />
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <style>

        html {
            box-sizing: border-box;
            overflow: -moz-scrollbars-vertical;
            overflow-y: scroll;
        }

        *,
        *:before,
        *:after {
            box-sizing: inherit;
        }

        body {
            margin: 0;
            background: #fafafa;
        }

        .qqgroup {
            float: right;
        }

        .info {
            float: left;
        }

        .download-contents {
            display: none;
        }
    </style>
    %(HeadContent)
</head>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
        <defs>
            <symbol viewBox="0 0 20 20" id="unlocked">
                <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
            </symbol>
            <symbol viewBox="0 0 20 20" id="locked">
                <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z" />
            </symbol>
            <symbol viewBox="0 0 20 20" id="close">
                <path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z" />
            </symbol>
            <symbol viewBox="0 0 20 20" id="large-arrow">
                <path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z" />
            </symbol>
            <symbol viewBox="0 0 20 20" id="large-arrow-down">
                <path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z" />
            </symbol>

            <symbol viewBox="0 0 24 24" id="jump-to">
                <path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="expand">
                <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" />
            </symbol>
        </defs>
    </svg>
    <div id="swagger-ui"></div>
    <!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
    <script>
        if (window.navigator.userAgent.indexOf("Edge") > -1) {
            console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
            window.fetch = undefined;
        }
    </script>
    <script src="./swagger-ui-bundle.js"></script>
    <script src="./swagger-ui-standalone-preset.js"></script>
    <script>
        var int = null;
        window.onload = function () {
            var configObject = JSON.parse('%(ConfigObject)');
            var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');

            // Apply mandatory parameters
            configObject.dom_id = "#swagger-ui";
            configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
            configObject.layout = "StandaloneLayout";

            // If oauth2RedirectUrl isn't specified, use the built-in default
            if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
                configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html");

            // Build a system
            const ui = SwaggerUIBundle(configObject);

            // Apply OAuth config
            ui.initOAuth(oauthConfigObject);


            int = setInterval(function () {
                getData();
            }, 1000);
            $("img").attr("src", "./logo/favicon-32x32.png");
        }
        function getData() {

            console.log(1);
            if ($(".qqgroup").length <= 0) {
                $('.info').after("<div class='qqgroup'><img  src='http://123.206.33.109:26898/QQGroup.png' alt='QQ二維碼' style='width: 200px;'></div><div style='clear: both;'></div>");
                console.log(2);
                clearInterval(int);
            }

        }

    </script>
</body>
</html>

 

我們可以在里邊簡單的修改 css 樣式,或者js 事件,但是注意,如果個人能力不是很高的話,建議不要修改。

 

2、然后我們修改中間件,替換掉 swagger 的默認首頁

 app.UseSwaggerUI(c =>
 {
     //根據版本名稱倒序 遍歷展示
     var ApiName = "Blog.Core";//這里你可以從appsettings.json中獲取,比如我封裝了一個類Appsettings.cs,具體查看我的源代碼 var version = "v1";
     c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
     
     // 將swagger首頁,設置成我們自定義的頁面,記得這個字符串的寫法:解決方案名.index.html
     c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Blog.Core.index.html");//這里是配合MiniProfiler進行性能監控的,《文章:完美基於AOP的接口性能分析》,如果你不需要,可以暫時先注釋掉,不影響大局。
     c.RoutePrefix = ""; //路徑配置,設置為空,表示直接在根域名(localhost:8001)訪問該文件,注意localhost:8001/swagger是訪問不到的,去launchSettings.json把launchUrl去掉,如果你想換一個路徑,直接寫名字即可,比如直接寫c.RoutePrefix = "doc";
 });

 

完成,就是這么簡單。

 

 

二、結語

對於接口是如何加權限驗證的?

讓我們帶着這些問題,繼續瀏覽下一篇吧,Swagger 3.3 JWT 權限,必看篇。

 

 

三、Github && Gitee

https://github.com/anjoy8/Blog.Core.git

https://gitee.com/laozhangIsPhi/Blog.Core


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM