Swashbuckle не генерирует пример XML правильно для свойств массива \ списка - PullRequest
0 голосов
/ 09 ноября 2018

Кажется, что swashbuckle \ swagger-ui (5.6 - с использованием swagger-ui) не генерирует пример XML правильно, когда у модели есть свойство, представляющее собой список.

Чтобы увидеть эту проблему:

1 - Создать пустой проект webapi (я использую asp.net)

2 - Добавить пару примеров моделей (я пошел с Заказчиком + Заказ на тестирование)

public class Customer
{
    public string AccountNumber { get; set; }
    [XmlArray("Orders"),XmlArrayItem("Order")]
    public List<Order> Orders { get;set; }
}

public class Order
{
    public string OrderNumber { get;set; }
}

3 - Создать контроллер, использующий FromBody для привязки к модели

public class CustomerController : ApiController
{
    public void Post([FromBody]Customer customer)
    {
        customer.ToString();
    }
}

4 - Изменить конфигурацию веб-API, чтобы разрешить простой XML

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Formatters.XmlFormatter.UseXmlSerializer = true;  //ADD THIS
    }
}

5 - Запустите сайт и с помощью / swagger измените тип содержимого параметра на xml и выберите пример модели. Вы найдете пример следующим образом.

<?xml version="1.0"?>
<Customer>
  <AccountNumber>string</AccountNumber>
  <Orders>
    <OrderNumber>string</OrderNumber>
  </Orders>
</Customer>

6 - Отправьте это с точкой останова в строке customer.ToString () в контроллере, и вы увидите, что коллекция Orders пуста

7 - измените XML в swagger-ui следующим образом и отправьте:

<?xml version="1.0"?>
<Customer>
  <AccountNumber>string</AccountNumber>
  <Orders>
    <Order><OrderNumber>string</OrderNumber></Order>
  </Orders>
</Customer>

8 - Коллекция Customer.Orders теперь правильно заполнена.

Каков наилучший способ исправить или обойти это в Swashbuckle?

(Есть несколько дискуссий по этому поводу, будь то ошибка в Swagger-UI или Swashbuckle, но мне особенно интересно обойти это с помощью Swashbuckle)

Ответы [ 2 ]

0 голосов
/ 31 июля 2019

Спасибо @mutex, но я обнаружил, что мне нужно сделать еще одну настройку:

internal class SwaggerFixArraysInXmlFilter : Swashbuckle.Swagger.ISchemaFilter
{
    // this fixes a Swagger bug that wasn't generating correct XML elements around List<> or array[] types
    public void Apply(Swashbuckle.Swagger.Schema schema, Swashbuckle.Swagger.SchemaRegistry schemaRegistry, System.Type type)
    {
        // Fix issues with xml array examples not generating correctly
        if (!type.IsValueType)
        {
            schema.xml = new Swashbuckle.Swagger.Xml { name = type.Name };
            if (schema.properties != null)
            {
                foreach (var property in schema.properties)
                {
                    //Array property, which wraps its elements
                    if (property.Value.type == "array")
                    {
                        property.Value.xml = new Swashbuckle.Swagger.Xml
                        {
                            name = $"{property.Key}",
                            wrapped = true
                        };
                        property.Value.items.xml = new Swashbuckle.Swagger.Xml
                        {
                            name = $"{property.Value.items.type}",
                            wrapped = true
                        };
                    }
                }
            }
        }
    }
}
0 голосов
/ 09 ноября 2018

Я нашел следующие работы:

1 - Добавить реализацию ISchemaFilter

internal class ApplySchemaVendorExtensions : ISchemaFilter
{
    public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
    {
        // Fix issues with xml array examples not generating correctly
        if (!type.IsValueType)
        {
            schema.xml = new Xml { name = type.Name };
            if(schema.properties != null)
            {
                foreach (var property in schema.properties)
                {
                    //Array property, which wraps its elements
                    if (property.Value.type == "array")
                    {
                        property.Value.xml = new Xml
                        {
                            name = $"{property.Key}",
                            wrapped = true
                        };
                    }
                }
            }
        }
    }
}

2 - закомментируйте эту строку в SwaggerConfig.cs

c.SchemaFilter<ApplySchemaVendorExtensions>();

Повторите тест в вопросе, и пример XML теперь работает напрямую. Как всегда, мне любопытно, есть ли лучшее решение ...

РЕДАКТИРОВАТЬ: На самом деле это странно работает в оригинальном проекте, у меня есть эта проблема, но в небольшом проекте по воспроизведению этого Quesion он ведет себя немного по-другому! Я отредактирую этот ответ, когда найду, почему ...

...