<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Asp.Net Core遇到Swagger(四)-Swashbuckle技巧c篇

          共 22463字,需瀏覽 45分鐘

           ·

          2021-09-16 17:34

          點(diǎn)擊上方藍(lán)色字體,關(guān)注我們


          1


          前言


          Swashbuckle技巧b篇,與Action相關(guān)的配置和操作,此處為c篇內(nèi)容。



          2


          實(shí)踐技巧



          2.1 忽略過(guò)時(shí)控制器和過(guò)時(shí)Action


          1)配置服務(wù)


          編輯ConfigureServices函數(shù)中的AddSwaggerGen函數(shù):

           services.AddSwaggerGen(c =>
           {
              ...
               #region 自定義DocInclusionPredicate判定規(guī)則
               //options.DocInclusionPredicate((docName, apiDesc) => {
               //   //判定當(dāng)前執(zhí)行是否為函數(shù)對(duì)象
               //   if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
               //       return false;
               //   //獲取函數(shù)對(duì)應(yīng)的自定義特性ApiVersionAttribute對(duì)應(yīng)的版本集合
               //   var versions = methodInfo.GetCustomAttributes(true)
               //   .OfType<ApiVersionAttribute>()
               //   .SelectMany(x => x.Versions);
               //   //判定版本集合中是否與當(dāng)前文檔匹配
               //   return versions.Any(x => $"v{x}" == docName);
               //});
               #endregion
           
               #region 忽略過(guò)時(shí)特性
               //忽略標(biāo)記過(guò)時(shí)的Action
               options.IgnoreObsoleteActions();
               //忽略標(biāo)記過(guò)時(shí)的Properties
               options.IgnoreObsoleteProperties();
               #endregion
              ...
           };


          2)添加案例控制器


          新建控制器IgnoreObsoleteController,內(nèi)容如下:

           namespace swaggertestbase.Controllers.v1
           {
               /// <summary>
               /// 忽略函數(shù)控制器
               /// </summary>
              [Route("api/[controller]")]
              [ApiController]
               public class IgnoreObsoleteController : ControllerBase
              {
                   /// <summary>
                   /// 獲取忽略函數(shù)數(shù)據(jù)
                   /// </summary>
                   /// <returns>返回結(jié)果</returns>
                  [Obsolete]
                  [HttpGet]
                   public string Get()
                  {
                       return "IgnoreObsolete";
                  }
                   
                  [HttpGet("{id}")]
                   //直接直接使用ApiExplorerSettings設(shè)置屬性IgnoreApi = true
                   //在當(dāng)前項(xiàng)目中該配置無(wú)效
            [ApiExplorerSettings(IgnoreApi = true)]
            public string GetById(int id)
                  {
                       return "IgnoreObsolete";
                  }
              }
           }


          運(yùn)行效果如下,在v1組中并不存在對(duì)應(yīng)的控制器以及對(duì)應(yīng)過(guò)時(shí)的函數(shù)。


          2.2 按照約定選擇Action函數(shù)


          1)自定義約定實(shí)現(xiàn)類


          新建類ApiExplorerGetsOnlyConvention,實(shí)現(xiàn)IActionModelConvention接口,進(jìn)行ActionModelConvention的自定義規(guī)則實(shí)現(xiàn)。

           /// <summary>
           /// 自定義實(shí)現(xiàn)只顯示Get請(qǐng)求的Action模型
           /// </summary>
           public class ApiExplorerGetsOnlyConvention : IActionModelConvention
           {
               public void Apply(ActionModel action)
              {
                   //依據(jù)請(qǐng)求是否為get請(qǐng)求處理是是否參與apijson的數(shù)據(jù)接口生成
                   action.ApiExplorer.IsVisible = action.Attributes.OfType<HttpGetAttribute>().Any();
              }
           }


          2)添加約定到服務(wù)配置


           services.AddControllers(configure => {
               //添加自定義apiexplor.groupname控制器模型屬性
               //configure.Conventions.Add(new ApiExplorerGroupVersionConvention());
               //自定義實(shí)現(xiàn)只顯示Get請(qǐng)求的Action模型
               configure.Conventions.Add(new ApiExplorerGetsOnlyConvention());
           });


          在控制器WeatherForecastController中添加一個(gè)Post請(qǐng)求函數(shù)。

           /// <summary>
           /// 獲取Post數(shù)據(jù)
           /// </summary>
           /// <returns>處理結(jié)果</returns>
           [HttpPost]
           public string Post()
           {
               return "處理結(jié)果";
           }


          運(yùn)行效果:

          2.3 自定義操作標(biāo)簽


          默認(rèn)Tag分組是以控制器名稱為依據(jù)進(jìn)行劃分,也可以通過(guò)TagActionsBy函數(shù)進(jìn)行配置。


          1)默認(rèn)分組



          2)自定義Tags分組


          修改ConfigureServicesAddSwaggerGen對(duì)應(yīng)配置,以下為依據(jù)Action的請(qǐng)求方法進(jìn)行分組的案例,需要注意的是IncludeXmlComments函數(shù),需要使用默認(rèn)配置,而不是設(shè)置IncludeXmlComments第二參數(shù)為true

           services.AddSwaggerGen(options =>
           {
              ...
               #region 添加xml注釋文件描述性信息
               //獲取當(dāng)前執(zhí)行程序集名稱+.xml,作為實(shí)際xml注釋文件名稱
               string filename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
               //拼接路徑-路徑間隔符由系統(tǒng)決定
               string path = System.IO.Path.Combine(System.AppContext.BaseDirectory, filename);
               //添加xml注釋文件到swaggergen中用于生成api json
               //此時(shí)需要選擇使用該函數(shù)的默認(rèn)配置
               options.IncludeXmlComments(path);
               #endregion
           
               #region 自定義Tags
               options.TagActionsBy(apidescr => {
                   return new string[] {
                   apidescr.HttpMethod
                  };
              });
               #endregion
              ...
           };
                                 
           services.AddControllers(configure => {
               //添加自定義apiexplor.groupname控制器模型屬性
               //configure.Conventions.Add(new ApiExplorerGroupVersionConvention());
               //自定義實(shí)現(xiàn)只顯示Get請(qǐng)求的Action模型
               //configure.Conventions.Add(new ApiExplorerGetsOnlyConvention());
           });


          運(yùn)行效果:


          2.4 自定義Action排序操作


          默認(rèn)情況下,Action能夠按Swagger規(guī)范,在添加到分組之前進(jìn)行排序操作,也可自定義排序規(guī)則,修改ConfigureServicesAddSwaggerGen對(duì)應(yīng)配置,此處以自定義排序規(guī)則Controller請(qǐng)求方法進(jìn)行排序。

           #region 自定義Tags
           options.TagActionsBy(apidescr => {
               return new string[] {
               apidescr.HttpMethod
              };
           });
           #endregion
           
           #region  自定義Tags排序
           options.OrderActionsBy(apidesc =>
           {
               //自定義Tag內(nèi)的Action排序
               return $"{apidesc.ActionDescriptor.RouteValues["controller"]}_{apidesc.HttpMethod}";
           });
           #endregion

          運(yùn)行效果:


          2.5 自定義架構(gòu)id


          如果在文檔生成器遇到復(fù)雜的傳入?yún)?shù)或響應(yīng)類型,生成器會(huì)自動(dòng)生成相應(yīng)Json Schema,并將其添加到全局Components/Schemas字典中。

          還是以天氣類WeatherForecast,默認(rèn)情況下,Api Json對(duì)應(yīng)請(qǐng)求鏈接http://localhost:5000/v1/swaggerapi.json內(nèi)容大致如下:

           {
             "paths": {
               "/WeatherForecast": {
                 "get": {
                   "tags": [
                     "GET"
                  ],
                   "summary": "獲取天氣預(yù)報(bào)信息",
                   "responses": {
                     "201": {
                       "description": "請(qǐng)求成功并且服務(wù)器創(chuàng)建了新的資源",
                       "content": {
                         "text/plain": {
                           "schema": {
                             "type": "array",
                             "items": {
                               // #/components/schemas/{schemasid}
                               "$ref": "#/components/schemas/WeatherForecast"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
             "components": {
               "schemas": {
                 "WeatherForecast": {
                   "type": "object",
                   "properties": {
                     "date": {
                       "type": "string",
                       "description": "日期",
                       "format": "date-time"
                    }
                  },
                   "additionalProperties": false,
                   "description": "天氣預(yù)報(bào)實(shí)體"
                }
              }
            }
           }


          修改服務(wù)中ConfigureServices的配置,自定義標(biāo)識(shí)的生成規(guī)則CustomSchemaIds。

           public void ConfigureServices(IServiceCollection services)
           {
                  services.AddSwaggerGen(
                  options =>
                      {
                           #region 自定義架構(gòu)Id
                           // 輸出對(duì)應(yīng)類型全名稱
              options.CustomSchemaIds(schema => schema.FullName);
              #endregion
                      }
                  );
           }


          運(yùn)行后,對(duì)應(yīng)輸出的Json結(jié)構(gòu)如下:

           {
             "paths": {
               "/WeatherForecast": {
                 "get": {
                   "tags": [
                     "GET"
                  ],
                   "summary": "獲取天氣預(yù)報(bào)信息",
                   "responses": {
                     "201": {
                       "description": "請(qǐng)求成功并且服務(wù)器創(chuàng)建了新的資源",
                       "content": {
                         "text/plain": {
                           "schema": {
                             "type": "array",
                             "items": {
                               // #/components/schemas/{schemasid}
                               "$ref": "#/components/schemas/swaggertestbase.WeatherForecast"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
             "components": {
               "schemas": {
                 // {schemasid}
                 "swaggertestbase.WeatherForecast": {
                   "type": "object",
                   "properties": {
                     "date": {
                       "type": "string",
                       "description": "日期",
                       "format": "date-time"
                    }
                  },
                   "additionalProperties": false,
                   "description": "天氣預(yù)報(bào)實(shí)體"
                }
              }
            }
           }


          2.6 覆蓋特定類型架構(gòu)[不常用]


          需要對(duì)特定類型進(jìn)行指定序列化處理時(shí),可以通過(guò)自定義架構(gòu)序列化類型處理。

          數(shù)據(jù)實(shí)體類:

           /// <summary>
           /// 天氣預(yù)報(bào)實(shí)體
           /// </summary>
           public class WeatherForecast
           {
               /// <summary>
               /// 日期
               /// </summary>
               public DateTime Date { get; set; }
               /// <summary>
               /// 溫度-攝氏度
               /// </summary>
               public int TemperatureC { get; set; }
               /// <summary>
               /// 溫度-華攝氏度
               /// </summary>
               public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
               /// <summary>
               /// 描述
               /// </summary>
               public string Summary { get; set; }
           }


          請(qǐng)求http://localhost:5000/v1/swaggerapi.json,原始Json架構(gòu)如下:

            "components": {
               "schemas": {
                 "WeatherForecast": {
                   "type": "object",
                   "properties": {
                     "date": {
                       "type": "string",
                       "description": "日期",
                       "format": "date-time"
                    },
                     "temperatureC": {
                       "type": "integer",
                       "description": "溫度-攝氏度",
                       "format": "int32"
                    },
                     "temperatureF": {
                       "type": "integer",
                       "description": "溫度-華攝氏度",
                       "format": "int32",
                       "readOnly": true
                    },
                     "summary": {
                       "type": "string",
                       "description": "描述",
                       "nullable": true
                    }
                  },
                   "additionalProperties": false,
                   "description": "天氣預(yù)報(bào)實(shí)體"
                }
              }
            }


          修改ConfigureServices中的AddSwaggerGen,設(shè)定類型序列化的架構(gòu)為字符串。

           services.AddSwaggerGen(
               options =>
              {
                   #region 覆蓋特定類型架構(gòu)
                   // 指定對(duì)應(yīng)的實(shí)體類型,類型架構(gòu)配置
                   options.MapType<WeatherForecast>(() => new Microsoft.OpenApi.Models.OpenApiSchema { Type = "string" });
                   #endregion
              }
              );


          設(shè)置以后,對(duì)應(yīng)的類型在架構(gòu)中,無(wú)生成,目前無(wú)考慮深究原因,運(yùn)行效果如下:

          2.7 使用過(guò)濾器擴(kuò)展生成器


          1)操作過(guò)濾器


          Swashbuckle會(huì)檢索每一個(gè)Asp.Net Core中的每一個(gè)ApiDescription,從中提取到對(duì)應(yīng)的OpenApiOperation,對(duì)應(yīng)OpenApiOperation類型和ApiDescription能夠通過(guò)操作過(guò)濾器列表實(shí)現(xiàn)傳遞。以包含權(quán)限認(rèn)證特性,響應(yīng)中401響應(yīng)狀態(tài)的操作過(guò)濾器為例。

          創(chuàng)建類AuthResponsesOperationFilter實(shí)現(xiàn)IOperationFilter。

           public class AuthResponsesOperationFilter : IOperationFilter
           {
               public void Apply(OpenApiOperation operation, OperationFilterContext context)
              {
                   var customAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
                      .Union(context.MethodInfo.GetCustomAttributes(true))
                      .OfType<AuthorizeAttribute>();
           
                   if (customAttributes.Any())
                  {
                       operation.Responses.Add("401", new OpenApiResponse { Description = "UnAuthorized" });
                  }
              }
           }


          給控制器中WeatherForecastController對(duì)應(yīng)Post函數(shù)添加特性Authorize。

           /// <summary>
           /// 天氣預(yù)報(bào)服務(wù)
           /// </summary>
           [ApiController]
           [Route("[controller]")]
           public class WeatherForecastController : ControllerBase
           {
              ........
               /// <summary>
               /// 獲取Post數(shù)據(jù)
               /// </summary>
               /// <returns>處理結(jié)果</returns>
              [HttpPost]
              [Authorize]
               public string Post()
              {
                   return "處理結(jié)果";
              }
              ........
           }


          添加到動(dòng)作過(guò)濾器列表中,

           services.AddSwaggerGen(
               options =>
              {
            #region 添加權(quán)限認(rèn)證響應(yīng)操作過(guò)濾器
            options.OperationFilter<AuthResponsesOperationFilter>();
            #endregion
              }
           );


          運(yùn)行效果如下:


          需要注意的是,過(guò)濾器管道是DI感知的。可以使用構(gòu)造函數(shù)參數(shù)創(chuàng)建過(guò)濾器,只要參數(shù)類型已在DI框架中注冊(cè),則它們將在過(guò)濾器實(shí)例化時(shí)自動(dòng)注入。


          2)架構(gòu)過(guò)濾器


          Swashbuckle為控制器操作公開(kāi)的每個(gè)參數(shù)、響應(yīng)和屬性類型生成 Swagger 樣式的 JSONSchema。生成后,它通過(guò)配置的架構(gòu)過(guò)濾器列表傳遞架構(gòu)和類型。

          創(chuàng)建枚舉類型。

           /// <summary>
           /// 自定義枚舉
           /// </summary>
           public enum MyEnum
           {
               A,
               B,
               C
           }


          創(chuàng)建SchemaFilterController控制器。

           [Route("api/[controller]")]
           [ApiController]
           public class SchemaFilterController : ControllerBase
           {
               /// <summary>
               /// 獲取SchemaFilter過(guò)濾器數(shù)據(jù)
               /// </summary>
               /// <param name="my">枚舉參數(shù)</param>
              [HttpGet]
               public void Get(MyEnum my)
              {
                   
              }
           }


          自定義類AutoRestSchemaFilter,實(shí)現(xiàn)ISchemaFilter。

           /// <summary>
           /// 自動(dòng)設(shè)置架構(gòu)過(guò)濾器
           /// </summary>
           public class AutoRestSchemaFilter : ISchemaFilter
           {
               public void Apply(OpenApiSchema schema, SchemaFilterContext context)
              {
                   var type = context.Type;
                   if (type.IsEnum)
                  {
                       schema.Extensions.Add("x-ms-enum", new OpenApiObject()
                      {
                          ["name"] = new OpenApiString(type.Name),
                          ["modelAsString"] = new OpenApiBoolean(true)
                      });
                  }
              }
           }


          添加到架構(gòu)過(guò)濾器中:

           ....
               services.AddSwaggerGen(
                           options =>
              {
                   #region 添加自定義架構(gòu)過(guò)濾器
            options.SchemaFilter<AutoRestSchemaFilter>();
            #endregion
              });
           ....


          訪問(wèn)http://localhost:5000/v1/swaggerapi.json,可以看到對(duì)應(yīng)結(jié)構(gòu)如下如下,x-ms-enum在對(duì)應(yīng)類型的架構(gòu)尾部。

           {
               "components": {
               "schemas": {
                 "MyEnum": {
                   "enum": [
                     0,
                     1,
                     2
                  ],
                   "type": "integer",
                   "description": "自定義枚舉",
                   "format": "int32",
                   "x-ms-enum": {
                     "name": "MyEnum",
                     "modelAsString": true
                  }
                }
              }
            }
           }


          通過(guò)上述例子,可以看出,對(duì)于枚舉等特殊類型,實(shí)際可以通過(guò)自定義Json schema的方式實(shí)現(xiàn)對(duì)應(yīng)字段值的備注含義。


          3)文檔過(guò)濾器


          Document Filters在遵守OpenApi的規(guī)范前提下,可以通過(guò)文檔過(guò)濾器對(duì)文檔進(jìn)行任意有效的Swagger Json。例如為當(dāng)前文檔添加額外的Tags,自定義過(guò)濾器TagDescriptionsDocumentFilter,實(shí)現(xiàn)IDocumentFilter。

           /// <summary>
           /// Tag描述文檔過(guò)濾器
           /// </summary>
           public class TagDescriptionsDocumentFilter : IDocumentFilter
           {
               public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
              {
                   swaggerDoc.Tags = new List<OpenApiTag> {
                       new OpenApiTag{
                          Name ="Pages",
                          Description = "分頁(yè)類"
                      },
                       new OpenApiTag{
                          Name ="Tests",
                          Description = "測(cè)試類"
                      }
                  };
              }
           }


          添加到現(xiàn)有的文檔過(guò)濾器中:

           public void ConfigureServices(IServiceCollection services)
           {
               services.AddSwaggerGen(
                   options =>
                  {
                       //忽略部分內(nèi)容
                       #region 添加自定義文檔過(guò)濾器
                       options.DocumentFilter<TagDescriptionsDocumentFilter>();
                       #endregion
                       //忽略部分內(nèi)容
                  }
                  );
           }


          請(qǐng)求http://localhost:5000/v1/swaggerapi.json,在返回結(jié)果中能夠看到如下部分結(jié)構(gòu):

           {
               //忽略無(wú)關(guān)項(xiàng)
               "tags": [
              {
                 "name": "Pages",
                 "description": "分頁(yè)類"
              },
              {
                 "name": "Tests",
                 "description": "測(cè)試類"
              }
            ]
           }


          后續(xù)文章將講解為Swagger添加安全驗(yàn)證。


          往期推薦



          點(diǎn)擊閱讀原文,更精彩~
          瀏覽 77
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情五月天成人电影 | 日韩777| 爽 好大 快 奶国产片 | 色亚洲色图 | 丁香五月天导航 |