【问题标题】:customize swagger ui to show parameter schema自定义 swagger ui 以显示参数架构
【发布时间】:2020-03-10 20:27:10
【问题描述】:

我有一个 swashbuckle swaggergen UI 输出,如下所示: [![提出请求][1]][1]

而且(出于某种原因),我不想使用典型的验证属性,而是在请求正文中进行验证。我的容器名称是一个 Azure Blob 存储容器,所以它必须是 3-63 个字符并且匹配一个简单的正则表达式(没有大写字母,基本上是字母数字)。

我想修改 UI 以显示这些要求...所以,我编写了 OperationFilter 和 Attribute。我假设我想修改 SwaggerParameters,在那里我注意到一个方便的模式,其中包含“MinLength”、“MaxLength”和“Pattern”等参数——换句话说,正是我想要在我的 UI 上显示的内容。所以我修改了那个。这是输出:

      "put": {
        "tags": [
          "Values"
        ],
        "summary": "API Operation – Create & Update\r\n::\r\nCreates a new content file entry in the containername provided.",
        "description": "If the container name has the word public in it, then the container\r\nshall be public otherwise the container, identified by the\r\ncontainername, shall be private. If the file, identified by the\r\nfilename parameter on the URI, already exists then the existing blob\r\nentry will be overwritten with the new fileData uploaded.",
        "operationId": "Put",
        "parameters": [
          {
            "name": "containername",
            "in": "path",
            "description": "The container the file resides in.",
            "required": true,
            "schema": {
              "maxLength": 63,
              "minLength": 3,
              "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
              "type": "string"
            }
          },
          {
            "name": "fileName",
            "in": "path",
            "description": "The name of the file uploaded. This shall become the block blob Id.",
            "required": true,
            "schema": {
              "maxLength": 75,
              "minLength": 1,
              "pattern": "\\S",
              "type": "string"
            }
          }
        ],

问题是,用户界面看起来一样。我应该修改什么来渲染这些值?

执行此操作的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using static Foo.SwaggerParameterDescriptions;

namespace Foo
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class SwaggerPathParameterDescriptions : Attribute
    {
        public enum Description
        {
            Default,
            MinLength,
            MaxLength,
            Pattern
        }

        public string ParameterName { get; set; }
        public Dictionary<Description, dynamic> Settings { get; set; }

        public SwaggerPathParameterDescriptions(string parameterName, string json)
        {
            Dictionary<string, dynamic> dict = JsonSerializer
                .Deserialize<Dictionary<string, dynamic>>(json);

            Dictionary<Description, dynamic> settings = dict.Entries()
                       .ToDictionary(entry => (Description)Enum.Parse(typeof(Description), (string)entry.Key),
                                     entry => entry.Value);

            ParameterName = parameterName;
            Settings = settings;
        }

        public IEnumerable<SwaggerParameterSchemaDescription> GetSwaggerParameters()
        {
            return Settings.Keys.Select(key =>
                new SwaggerParameterSchemaDescription { ParameterName = key, Value = Settings[key] });
        }
    }

    public class SwaggerParameterSchemaDescription
    {
        public Description ParameterName { get; set; }
        public dynamic Value { get; set; }

        public void ApplyTo(OpenApiParameter param)
        {
            string representation = $"{Value}";
            switch (ParameterName)
            {
                case Description.Default:
                    param.Schema.Default = new OpenApiString(representation); // Path Parameters must be strings!
                    break;
                case Description.MinLength:
                    param.Schema.MinLength = Int32.Parse(representation);
                    break;
                case Description.MaxLength:
                    param.Schema.MaxLength = Int32.Parse(representation);
                    break;
                case Description.Pattern:
                    param.Schema.Pattern = representation;
                    break;
                default:
                    throw new InvalidOperationException();
            }
        }
    }

    public class AddSettings : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            foreach (var param in operation.Parameters)
            {
                var actionParam = context.ApiDescription.ActionDescriptor.Parameters.First(p => p.Name == param.Name);
                if (actionParam != null)
                {
                    context.MethodInfo
                        .GetCustomAttributes(true)
                        .OfType<SwaggerPathParameterDescriptions>()
                        .Where(p => p.ParameterName == param.Name)
                        .ToList()
                        .ForEach(customAttribute =>
                    {
                        foreach (SwaggerParameterSchemaDescription description in customAttribute.GetSwaggerParameters())
                        {
                            description.ApplyTo(param);
                        }
                    });
                }

            }
        }
    }
}

在启动中:

services.AddSwaggerGen(c => {
                c.OperationFilter<AddSettings>();

然后使用like:

        [HttpPut("{containername}/contentfiles/{fileName}")]
        [SwaggerPathParameterDescriptions("containername", "{\"MinLength\":3,\"MaxLength\":63,\"Pattern\":\"^[a-z0-9]+(-[a-z0-9]+)*$\"}")]
        [SwaggerPathParameterDescriptions("fileName", "{\"MinLength\":1,\"MaxLength\":75,\"Pattern\":\"\\\\S\"}")]
        [SwaggerResponseHeader(StatusCodes.Status201Created, "Location", "string", "Location of the newly created resource")]
        [ProducesResponseType(StatusCodes.Status201Created)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
        [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status503ServiceUnavailable)]
        public ActionResult Put(string containername, string fileName, IFormFile fileData)

我的问题是它没有渲染。 :( 我还有更多工作要做?还是我修改了错误的值?

【问题讨论】:

  • 由于某种原因它不允许我发布我的图片..当我拖放它然后发布时,它说“身体不能包含我的点堆栈点 imgur dot com slash nTFyg.png”图像在那里可见
  • 你的API定义是swagger: "2.0"还是openapi: 3.0.0
  • "openapi": "3.0.1", ... 它从 Swashbuckle.AspNetCore.SwaggerGen 生成
  • 我认为这被否决真是太搞笑了......这里最活跃的招摇的贡献者之一跳出来回答我的问题

标签: asp.net-core swagger swagger-ui openapi swashbuckle


【解决方案1】:

仅当使用 showCommonExtensions: true 选项配置时,Swagger UI 才会显示参数 minLengthmaxLengthpatternThis answer 展示了如何通过 Swashbuckle 配置启用此选项。

但是,您必须等待 Swagger UI 的下一个版本才能使 showCommonExtensions: true 选项适用于 OpenAPI 3.0 定义。代码在Swagger UI repositorymaster 分支中,但尚未发布新版本。如果需要,您可以从 master 分支自己构建 Swagger UI,并在您的项目中使用生成的 dist 资产来立即获得此功能。

【讨论】:

  • 当前是否支持任何其他版本?我认为 swashbuckle.aspnetcore 不会弹出 SwaggerUI,有一个 dll
  • Swashbuckle 让您可以在 Swagger UI 中使用 custom index.html,也许还有一种方法可以替换捆绑的 CSS 和 JS。我自己没有使用过 Swashbuckle,所以我不能更具体,抱歉。
  • 哇哦,默认他们要求你直接加载swagger ui :) 谢谢!
  • 你知道这是否应该在npm i 的 swagger-ui 3.25.0 上工作?或者我需要拉主 - 如果是这样,我从哪个文件夹复制两个 js src 文件? (它 看起来 像 master 是在 3.25.0 .. 但这对我不起作用,如果 bundle 和 Standalone 是我需要获取更新的唯一两个文件)
  • 我修改了我的 index.html 以在控制台上给我 configObject,我可以看到 configObject.showCommonExtensions =&gt; true .. 我会从这里打开一个新问题。感谢 agin 的帮助
猜你喜欢
  • 1970-01-01
  • 2018-10-04
  • 2017-01-24
  • 2022-12-21
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多