Swagger генерирует неверный URL для словаря в ASP.CORE 3

Swagger генерирует неверный URL -адрес, когда модель, извлеченная из строки запроса, имеет словарь в качестве одного из свойств. Как указать Swagger изменить формат словаря в URL -адресе или определить схему входных параметров вручную, без автогенерации? Пробовал использовать Swashbuckle и NSwag.

Контроллер

public class RecordsController : ControllerBase
{
  [HttpGet]
  [Route("services/records")]
  public async Task<IActionResult> Records([FromQuery] QueryModel queryModel)
  {
    return null;
  }
}

Модель ввода - строка запроса

public class QueryModel 
{
  public int Page { get; set; }
  public int Count { get; set; }
  public Dictionary<Columns, string> Conditions { get; set; }
}

Пользовательский интерфейс Swagger показывает этот формат для свойства "Условия" в модели запроса.

{
  "UserId": "string",
  "GroupId": "string",
  "RecordId": "string"
}

Созданный Swagger URL - Open API v2 - не будет привязан к "Условиям"

/services/records?Page=0&Count=5&Conditions={"UserId":"1"} 

Созданный Swagger URL - Open API v3 - не будет привязан к "Условиям"

/services/records?Page=0&Count=5&UserId=1 

Пользовательский URL - работает должным образом и инициализирует "Условия" с{ "UserId", "1" }

/services/records?Page=0&Count=5&Conditions[UserId]=1 

Вопрос

Как заставить Swagger отображать URL как PropertyName[Key]=Value для свойства типа Dictionary?

Альтернативный вопрос

Это не решение, но если я таким образом определю значение по умолчанию для своего входного параметра, Swagger создаст правильный URL.

{
  "Conditions[UserId]": "1",
  "Conditions[GroupId]": "2"
}

URL теперь правильный и правильно привязан к модели

/services/records?Page=0&Count=5&Conditions[UserId]=1&Conditions[GroupId]=2 

Есть ли способ изменить значение по умолчанию, отображаемое в Swagger для типа ввода словаря?

1 ответ

Вам нужно будет установить стиль запроса deepObject для определения запроса

В настоящее время это поддерживается NSwag через SwaggerParameterStyle, для которого вы установите значениеdeepObject.

Мне также было любопытно, как это сделать без NSwag, поэтому я взглянул на https://editor.swagger.io/

Здесь вы можете предоставить ему свой статический json swagger, и он сгенерирует вам сервер, если вы хотите увидеть другой способ создания той же настройки.

Образец модели для словаря

[DataContract]
public partial class Dictionary : IEquatable<Dictionary>
{ 
    /// <summary>
    /// Gets or Sets Word
    /// </summary>
    [DataMember(Name="word")]
    public string Word { get; set; }

    /// <summary>
    /// Gets or Sets Define
    /// </summary>
    [DataMember(Name="define")]
    public string Define { get; set; }

Образец контроллера

    /// <summary>
    /// Get word definition
    /// </summary>
    /// <remarks>Get me the word definitions</remarks>
    /// <param name="dictionary">Status values that need to be considered for filter</param>
    /// <response code="200">successful operation</response>
    [HttpGet]
    [Route("/v2/book")]
    [ValidateModelState]
    [SwaggerOperation("BookGet")]
    public virtual IActionResult BookGet([FromQuery][Required()]Dictionary dictionary)

Пример запроса Raw Swagger

/book:
  get:
    summary: Get word definition
    description: Get me the word definitions
    parameters:
    - name: dictionary
      in: query
      description: Status values that need to be considered for filter
      required: true
      style: deepObject
      schema:
        type: object
        properties:
          word: 
            type: string
          define:
            type: string

Посмотрите на стиль deepObject в https://swagger.io/specification/

Другие вопросы по тегам