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

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

2.13 自定义架构id

如果在文档生成器遇到复杂的传入参数或响应类型,生成器会自动生成相应Json Schema,并将其添加到全局Components/Schemas字典中。

还是以天气类WeatherForecast,默认情况下,Api Json对应请求链接http://localhost:5000/v1/swaggerapi.json内容大致如下:

{
  "paths": {
    "/WeatherForecast": {
      "get": {
        "tags": [
          "GET"
        ],
        "summary": "获取天气预报信息",
        "responses": {
          "201": {
            "description": "请求成功并且服务器创建了新的资源",
            "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": "天气预报实体"
      }
    }
  }
}

修改服务中ConfigureServices的配置,自定义标识的生成规则CustomSchemaIds

public void ConfigureServices(IServiceCollection services)
{
       services.AddSwaggerGen(
          options =>
            {
                #region 自定义架构Id
                // 输出对应类型全名称
          options.CustomSchemaIds(schema => schema.FullName);
          #endregion
            }
       );
}

运行后,对应输出的Json结构如下:

{
  "paths": {
    "/WeatherForecast": {
      "get": {
        "tags": [
          "GET"
        ],
        "summary": "获取天气预报信息",
        "responses": {
          "201": {
            "description": "请求成功并且服务器创建了新的资源",
            "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": "天气预报实体"
      }
    }
  }
}

2.14 覆盖特定类型架构[不常用]

需要对特定类型进行指定序列化处理时,可以通过自定义架构序列化类型处理。

数据实体类:

/// <summary>
/// 天气预报实体
/// </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; }
}

请求http://localhost:5000/v1/swaggerapi.json,原始Json架构如下:

"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": "天气预报实体"
      }
    }
  }

修改ConfigureServices中的AddSwaggerGen,设定类型序列化的架构为字符串。

services.AddSwaggerGen(
    options =>
    {
        #region 覆盖特定类型架构
        // 指定对应的实体类型,类型架构配置
        options.MapType<WeatherForecast>(() => new Microsoft.OpenApi.Models.OpenApiSchema { Type = "string" });
        #endregion
    }
    );

设置以后,对应的类型在架构中,无生成,目前无考虑深究原因,运行效果如下:

2.15 使用过滤器扩展生成器

1)操作过滤器

Swashbuckle会检索每一个Asp.Net Core中的每一个ApiDescription,从中提取到对应的OpenApiOperation,对应OpenApiOperation类型和ApiDescription能够通过操作过滤器列表实现传递。以包含权限认证特性,响应中401响应状态的操作过滤器为例。

创建类AuthResponsesOperationFilter实现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对应Post函数添加特性Authorize

/// <summary>
/// 天气预报服务
/// </summary>
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    ........
    /// <summary>
    /// 获取Post数据
    /// </summary>
    /// <returns>处理结果</returns>
    [HttpPost]
    [Authorize]
    public string Post()
    {
        return "处理结果";
    }
    ........
}

添加到动作过滤器列表中,

services.AddSwaggerGen(
    options =>
    {
    #region 添加权限认证响应操作过滤器
    options.OperationFilter<AuthResponsesOperationFilter>();
    #endregion
    }
);

运行效果如下:

需要注意的是,过滤器管道是DI感知的。 可以使用构造函数参数创建过滤器,只要参数类型已在DI框架中注册,则它们将在过滤器实例化时自动注入。

2)架构过滤器

Swashbuckle为控制器操作公开的每个参数、响应和属性类型生成 Swagger 样式的 JSONSchema。 生成后,它通过配置的架构过滤器列表传递架构和类型。

创建枚举类型,

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

创建SchemaFilterController控制器,

[Route("api/[controller]")]
[ApiController]
public class SchemaFilterController : ControllerBase
{
    /// <summary>
    /// 获取SchemaFilter过滤器数据
    /// </summary>
    /// <param name="my">枚举参数</param>
    [HttpGet]
    public void Get(MyEnum my)
    { 
    }
}

自定义类AutoRestSchemaFilter,实现ISchemaFilter

/// <summary>
/// 自动设置架构过滤器
/// </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)
            });
        }
    }
}

添加到架构过滤器中,

....
    services.AddSwaggerGen(
                options =>
    {
        #region 添加自定义架构过滤器
    options.SchemaFilter<AutoRestSchemaFilter>();
    #endregion
    });
....

访问http://localhost:5000/v1/swaggerapi.json,可以看到对应结构如下如下,x-ms-enum在对应类型的架构尾部。

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

通过上述例子,可以看出,对于枚举等特殊类型,实际可以通过自定义Json schema的方式实现对应字段值的备注含义。

3)文档过滤器

Document Filters在遵守OpenApi的规范前提下,可以通过文档过滤器对文档进行任意有效的Swagger Json。例如为当前文档添加额外的Tags,自定义过滤器TagDescriptionsDocumentFilter,实现IDocumentFilter

/// <summary>
/// Tag描述文档过滤器
/// </summary>
public class TagDescriptionsDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.Tags = new List<OpenApiTag> { 
            new OpenApiTag{ 
               Name ="Pages",
               Description = "分页类"
            },
            new OpenApiTag{
               Name ="Tests",
               Description = "测试类"
            }
        };
    }
}

添加到现有的文档过滤器中,

public void ConfigureServices(IServiceCollection services)
{
    services.AddSwaggerGen(
        options =>
        {
            //忽略部分内容
            #region 添加自定义文档过滤器
            options.DocumentFilter<TagDescriptionsDocumentFilter>();
            #endregion
            //忽略部分内容
        }
        );
}

请求http://localhost:5000/v1/swaggerapi.json,在返回结果中能够看到如下部分结构:

{
    //忽略无关项
    "tags": [
    {
      "name": "Pages",
      "description": "分页类"
    },
    {
      "name": "Tests",
      "description": "测试类"
    }
  ]
}

后续文章将讲解为Swagger添加安全验证。



相关文章
|
6天前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
6天前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
18 3
|
28天前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
2月前
|
开发框架 监控 .NET
开发者的革新利器:ASP.NET Core实战指南,构建未来Web应用的高效之道
【8月更文挑战第28天】本文探讨了如何利用ASP.NET Core构建高效、可扩展的Web应用。ASP.NET Core是一个开源、跨平台的框架,具有依赖注入、配置管理等特性。文章详细介绍了项目结构规划、依赖注入配置、中间件使用及性能优化方法,并讨论了安全性、可扩展性以及容器化的重要性。通过这些技术要点,开发者能够快速构建出符合现代Web应用需求的应用程序。
35 0
|
28天前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
28 7
|
26天前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
38 0
|
2月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
36 0
|
2月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
2月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
91 0
|
5月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
158 0