настроить интерфейс Swagger для отображения схемы параметров - PullRequest
0 голосов
/ 10 марта 2020

У меня есть вывод пользовательского интерфейса swashbuckle swaggergen, который выглядит следующим образом: [! [Put request] [1]] [1]

И (по причинам) я не хочу использовать типичный атрибут проверки вместо этого я проверяю в теле запроса. Мое имя контейнера - это Azure контейнер хранилища BLOB-объектов, поэтому он должен состоять из 3-63 символов и соответствовать простому регулярному выражению (без прописных букв, в основном букв-цифр c).

Я хотел бы изменить Пользовательский интерфейс, чтобы также показать эти требования ... Итак, я написал OperationFilter и Attribute. Я предположил, что хочу изменить SwaggerParameters, и там я заметил удобную схему с такими параметрами, как «MinLength», «MaxLength» и «Pattern» - другими словами, именно то, что я хочу показать в своем пользовательском интерфейсе. Поэтому я изменил это. Вот вывод:

      "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>();

, затем используйте:

        [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)

Моя проблема в том, что это не рендеринг. :( У меня есть больше работы? Или я изменяю неправильные значения?

1 Ответ

1 голос
/ 11 марта 2020

Swagger UI отображает параметры minLength, maxLength и pattern только тогда, когда он настроен с опцией showCommonExtensions: true. Этот ответ показывает, как включить эту опцию через конфигурацию Swashbuckle.

Однако вам придется подождать следующего выпуска Swagger UI, чтобы опция showCommonExtensions: true работала для Определения OpenAPI 3.0. Код находится в master ветви хранилища Swagger UI , но новая версия еще не выпущена. Если вы хотите, вы можете создать Swagger UI самостоятельно из ветви master и использовать полученные ресурсы dist в своем проекте, чтобы получить эту функциональность прямо сейчас.

...