From 8dfbd8615bb7329fef30813ce86ff7a43383b2bf Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Sun, 20 Dec 2020 20:07:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SwaggerStudy.Models/Enum.cs | 8 ++--- SwaggerStudy/Controllers/StudentController.cs | 3 ++ SwaggerStudy/Documents/README_zh.md | 24 ++++++------- SwaggerStudy/Startup.cs | 2 ++ SwaggerStudy/StartupTest.cs | 18 ++++++++-- .../AuthResponsesOperationFilter.cs | 2 +- .../SwaggerFilters/EnumSchemaFilter.cs | 34 +++++++++++++++++++ .../TagDescriptionsDocumentFilter.cs | 33 ++++++++++++++++++ SwaggerStudy/WebApp/JsonOption.cs | 26 ++++++++++++++ 9 files changed, 128 insertions(+), 22 deletions(-) rename SwaggerStudy/{Filters => SwaggerFilters}/AuthResponsesOperationFilter.cs (97%) create mode 100644 SwaggerStudy/SwaggerFilters/EnumSchemaFilter.cs create mode 100644 SwaggerStudy/SwaggerFilters/TagDescriptionsDocumentFilter.cs create mode 100644 SwaggerStudy/WebApp/JsonOption.cs diff --git a/SwaggerStudy.Models/Enum.cs b/SwaggerStudy.Models/Enum.cs index c57c6da..adf77ba 100644 --- a/SwaggerStudy.Models/Enum.cs +++ b/SwaggerStudy.Models/Enum.cs @@ -6,26 +6,26 @@ using System.Text; namespace SwaggerStudy.Models { /// - /// 性别 + /// 性别枚举 /// public enum GenderEnum { /// /// 女性 /// - [Description("原材料仓")] + [Description("女")] Female=0, /// /// 男性 /// - [Description("原材料仓")] + [Description("男")] Male=1, /// /// 保密 /// - [Description("原材料仓")] + [Description("保密")] Secrecy=3, } } diff --git a/SwaggerStudy/Controllers/StudentController.cs b/SwaggerStudy/Controllers/StudentController.cs index 3b7a929..0ccb21d 100644 --- a/SwaggerStudy/Controllers/StudentController.cs +++ b/SwaggerStudy/Controllers/StudentController.cs @@ -69,6 +69,9 @@ namespace SwaggerStudy.Controllers /// /// 我是Remark注释 /// 学生Id(变量在路由中时,example才有用) + /// + /// 查询到的学生 + /// [AllowAnonymous] [HttpGet("{studentId:int}")] public IActionResult Get([FromRoute]int studentId) diff --git a/SwaggerStudy/Documents/README_zh.md b/SwaggerStudy/Documents/README_zh.md index e780072..4a28ebb 100644 --- a/SwaggerStudy/Documents/README_zh.md +++ b/SwaggerStudy/Documents/README_zh.md @@ -840,10 +840,8 @@ _注意: 过滤器管道可识别。也就是说,您可以使用构造函数 #### Schema 筛选器 #### -Swashbuckle generates a Swagger-flavored [JSONSchema](http://swagger.io/specification/#schemaObject) for every parameter, response and property type that's exposed by your controller actions. Once generated, it passes the schema and type through the list of configured Schema Filters. - -The example below adds an AutoRest vendor extension (see https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-enum) to inform the AutoRest tool how enums should be modelled when it generates the API client. - +Swashbuckle会为`controller` `actions`公开的每个`parameter` `response` `property` `Type` 生成Swagger风格的[JSONSchema](http://swagger.io/specification/#schemaObject)。生成后,它将在已配置的架构过滤器列表中传递架构和类型。 +下面的示例下面的示例添加了一个AutoRest供应商扩展([参阅](https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-enum)),以通知AutoRest工具在生成API客户端时应该如何对枚举进行建模。 ```csharp // AutoRestSchemaFilter.cs public class AutoRestSchemaFilter : ISchemaFilter @@ -875,9 +873,8 @@ services.AddSwaggerGen(c => #### Document 筛选器 #### -Once an `OpenApiDocument` has been generated, it too can be passed through a set of pre-configured Document Filters. This gives full control to modify the document however you see fit. To ensure you're still returning valid Swagger JSON, you should have a read through the [specification](http://swagger.io/specification/) before using this filter type. - -The example below provides a description for any tags that are assigned to operations in the document: +一旦生成了`OpenApiDocument`,它也可以通过一组预先配置的文档过滤器进行传递。这样您就可以完全控制自己修改文档的方式。为了确保仍然返回有效的Swagger JSON,在使用此过滤器类型之前,您应该通读[specification](http://swagger.io/specification/)。 +下面的示例提供了分配给文档中操作的任何标记的说明: ```csharp public class TagDescriptionsDocumentFilter : IDocumentFilter @@ -892,13 +889,12 @@ public class TagDescriptionsDocumentFilter : IDocumentFilter } ``` -_NOTE: If you're using the `SwaggerUI` middleware, the `TagDescriptionsDocumentFilter` demonstrated above could be used to display additional descriptions beside each group of Operations._ - -### Add Security Definitions and Requirements ### +_注意:如果您使用的是`SwaggerUI`中间件,那么上面演示的`TagDescriptionsDocumentFilter`可以用来在每一组操作旁边显示额外的描述。_ -In Swagger, you can describe how your API is secured by defining one or more security schemes (e.g basic, api key, oauth2 etc.) and declaring which of those schemes are applicable globally OR for specific operations. For more details, take a look at the [Security Requirement Object in the Swagger spec.](https://swagger.io/specification/#securityRequirementObject). +### 添加安全定义和要求 ### -In Swashbuckle, you can define schemes by invoking the `AddSecurityDefinition` method, providing a name and an instance of `OpenApiSecurityScheme`. For example you can define an [OAuth 2.0 - implicit flow](https://oauth.net/2/) as follows: +在Swagger中,您可以通过定义一个或多个安全方案(例如basic、API key、oauth2等)并声明这些方案中的哪一个适用于全局或特定操作,来描述API是如何受到保护的。有关更多详细信息,请查看[Swagger规范中的安全需求对象](https://swagger.io/specification/#securityRequirementObject). +在swashbuck中,可以通过调用`AddSecurityDefinition`方法来定义方案,提供`OpenApiSecurityScheme`的名称和实例。例如,您可以定义[OAuth 2.0-隐式流](https://oauth.net/2/)具体如下: ```csharp // Startup.cs @@ -926,7 +922,7 @@ services.AddSwaggerGen(c => }; ``` -_NOTE: In addition to defining a scheme, you also need to indicate which operations that scheme is applicable to. You can apply schemes globally (i.e. to ALL operations) through the `AddSecurityRequirement` method. The example below indicates that the scheme called "oauth2" should be applied to all operations, and that the "readAccess" and "writeAccess" scopes are required. When applying schemes of type other than "oauth2", the array of scopes MUST be empty._ +_注意:除了定义方案外,还需要指明该方案适用于哪些操作。您可以通过`AddSecurityRequirement`方法全局应用方案(即,应用于所有操作)。下面的示例表明,名为"oauth2"的方案应该应用于所有操作,并且需要"readAccess"和"writeAccess"范围。当应用"oauth2"以外类型的方案时,作用域数组必须为空。_ ```csharp c.AddSwaggerGen(c => @@ -946,7 +942,7 @@ c.AddSwaggerGen(c => }) ``` -If you have schemes that are only applicable for certain operations, you can apply them through an Operation filter. For example, the following filter adds OAuth2 requirements based on the presence of the `AuthorizeAttribute`: +如果您有仅适用于某些操作的方案,则可以通过操作筛选器应用这些方案。例如,以下筛选器根据`AuthorizeAttribute`的存在添加OAuth2要求: ```csharp // SecurityRequirementsOperationFilter.cs diff --git a/SwaggerStudy/Startup.cs b/SwaggerStudy/Startup.cs index 7eee8c9..468ce4b 100644 --- a/SwaggerStudy/Startup.cs +++ b/SwaggerStudy/Startup.cs @@ -40,6 +40,8 @@ namespace SwaggerStudy .AddControllers() .AddJsonOptions(jsonOption=> { + jsonOption.JsonSerializerOptions.WriteIndented = true; + jsonOption.JsonSerializerOptions.AllowTrailingCommas = true; jsonOption.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter()); jsonOption.JsonSerializerOptions.Encoder= System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All); }); diff --git a/SwaggerStudy/StartupTest.cs b/SwaggerStudy/StartupTest.cs index 6ae9e68..150aa32 100644 --- a/SwaggerStudy/StartupTest.cs +++ b/SwaggerStudy/StartupTest.cs @@ -19,6 +19,7 @@ using Swashbuckle.AspNetCore.SwaggerUI; using SwaggerStudy.Services; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Any; namespace SwaggerStudy { @@ -38,10 +39,12 @@ namespace SwaggerStudy { services .AddControllers() - .AddJsonOptions(jsonOption=> + .AddJsonOptions(jsonOption => { + jsonOption.JsonSerializerOptions.WriteIndented = true; + jsonOption.JsonSerializerOptions.AllowTrailingCommas = true; jsonOption.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter()); - jsonOption.JsonSerializerOptions.Encoder= System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All); + jsonOption.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All); }); //注入SwaggerGen @@ -71,7 +74,14 @@ namespace SwaggerStudy //此对象可以使用规范扩展进行扩展 Extensions = new Dictionary() { - + { + "OpenApiInfo扩展", + new OpenApiObject + { + ["OpenApiObjectName"] = new OpenApiString("OpenApiInfo扩展_1"), + ["modelAsString"] = new OpenApiBoolean(true) + } + } } }); @@ -94,6 +104,8 @@ namespace SwaggerStudy #region 过滤器 setup.OperationFilter(); + setup.SchemaFilter(); + setup.DocumentFilter(); #endregion }); diff --git a/SwaggerStudy/Filters/AuthResponsesOperationFilter.cs b/SwaggerStudy/SwaggerFilters/AuthResponsesOperationFilter.cs similarity index 97% rename from SwaggerStudy/Filters/AuthResponsesOperationFilter.cs rename to SwaggerStudy/SwaggerFilters/AuthResponsesOperationFilter.cs index 0825b73..b5dad95 100644 --- a/SwaggerStudy/Filters/AuthResponsesOperationFilter.cs +++ b/SwaggerStudy/SwaggerFilters/AuthResponsesOperationFilter.cs @@ -25,7 +25,7 @@ namespace SwaggerStudy if (authAttributes .OfType().Any() || authAttributes .OfType().Any()) { operation.Responses.Add("401", new OpenApiResponse { Description = "未授权" }); - operation.Responses.Add("403", new OpenApiResponse { Description = "" }); + operation.Responses.Add("403", new OpenApiResponse { Description = "无权限" }); } } } diff --git a/SwaggerStudy/SwaggerFilters/EnumSchemaFilter.cs b/SwaggerStudy/SwaggerFilters/EnumSchemaFilter.cs new file mode 100644 index 0000000..da9c1a7 --- /dev/null +++ b/SwaggerStudy/SwaggerFilters/EnumSchemaFilter.cs @@ -0,0 +1,34 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using Microsoft.OpenApi; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Models; + +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace SwaggerStudy +{ + public class EnumSchemaFilter : 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) + } + ); + }; + } + } +} diff --git a/SwaggerStudy/SwaggerFilters/TagDescriptionsDocumentFilter.cs b/SwaggerStudy/SwaggerFilters/TagDescriptionsDocumentFilter.cs new file mode 100644 index 0000000..ba962cd --- /dev/null +++ b/SwaggerStudy/SwaggerFilters/TagDescriptionsDocumentFilter.cs @@ -0,0 +1,33 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +using Microsoft.OpenApi; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Models; + +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace SwaggerStudy +{ + public class TagDescriptionsDocumentFilter : IDocumentFilter + { + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + //输出整个SwaggerDoc为Json字符串 + var JSON = JsonSerializer.Serialize(swaggerDoc, SystemTextJsonOption.DefaultJsonSerializerOptions); + Console.WriteLine(JSON); + + swaggerDoc.Tags = new List + { + new OpenApiTag { Name = "Products", Description = "Browse/manage the product catalog" }, + new OpenApiTag { Name = "Orders", Description = "Submit orders" } + }; + } + } +} diff --git a/SwaggerStudy/WebApp/JsonOption.cs b/SwaggerStudy/WebApp/JsonOption.cs new file mode 100644 index 0000000..973e7fb --- /dev/null +++ b/SwaggerStudy/WebApp/JsonOption.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace SwaggerStudy +{ + public static class SystemTextJsonOption + { + public static JsonSerializerOptions DefaultJsonSerializerOptions + { + get { + + var jsonOptions = new JsonSerializerOptions(); + jsonOptions.WriteIndented = true; + jsonOptions.AllowTrailingCommas = true; + jsonOptions.Converters.Add(new DatetimeJsonConverter()); + jsonOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All); + + return jsonOptions; + } + } + } +}