ASP.NET Core 2.0 — динамическое определение модели для документации

У нас есть набор REST-сервисов. Сервисы принимают модели в формате json в запросе POST и возвращают модели в формате json в ответе POST. Однако эти модели не являются физически скомпилированными типами в наших проектах ASP.NET Core 2.0. Вместо этого они представляют собой сопоставленные объекты, которые сопоставляются с нашими внутренними типами. т.е. json, который обслуживается, — это просто слой поверх наших основных объектов, которые урезаны с целью предоставления данных третьим сторонам.

Однако сущности должны быть задокументированы с помощью Swagger. Swashbuckle отлично справляется с этой задачей. Это делается через пространство имен Microsoft.AspNetCore.Mvc.ApiExplorer. Сейчас я пытаюсь определить метаданные для сущностей, обслуживаемых в json с этим пространством имен. Однако мне не очень везет. Я хочу определить тип, который не основан на физическом типе в моем проекте. Я рад определить имя, свойства и т. д., но я ничего не могу сделать с тем, что сделал. Например, абстрактному классу ModelMetadata требуется аргумент типа ModelMetadataIdentity, но этот тип не принимает никаких аргументов в конструкторе, а все важные свойства доступны только для получения. Так, например, я буквально не могу установить свойство Name в ModelMetadataIdentity. Я предполагаю, что это сбой в коде, из-за которого я даже могу создать ModelMetadataIdentity. Я предполагаю, что класс должен был быть абстрактным.

Например, есть статический метод ForType, который компилируется и не генерирует никаких исключений, например:

        var customModelMetadataProvider = new CustomModelMetadataProvider(ModelMetadataIdentity.ForType(typeof(TaskInfo)));
        context.ApiDescription.SupportedResponseTypes.Add(new Microsoft.AspNetCore.Mvc.ApiExplorer.ApiResponseType { ModelMetadata = customModelMetadataProvider });

Но это ничего не делает. В документации Swagger нет документации для TaskInfo. Но, что более важно, для меня это бесполезно, потому что TaskInfo — это предварительно скомпилированный тип, и я пытаюсь определить концептуальный, а не физический тип.

Чтобы понять, о чем я говорю, вы можете посмотреть пример здесь: https://github.com/Microsoft/aspnet-api-versioning/tree/master/samples/webapi/SwaggerODataWebApiSample . Например, Order и Person определены в проекте как типы, но я хочу создавать метаданные для этих типов динамически.

Как определить концептуальный (динамический) тип с помощью пространства имен Microsoft.AspNetCore.Mvc.ApiExplorer? Как заставить Swashbuckle распознавать метаданные, которые я определил с помощью этого пространства имен?

PS: Я знаю, что некоторые люди подумают: "Почему бы вам просто не написать модели в коде и не скомпилировать их?". Что ж, очевидно, это можно сделать, но это добавляет дополнительный шаг к настройке служб REST, который не должен быть необходим. Сопоставление наших внутренних сущностей с внешними сущностями выполняется с помощью конфигурации, а не кода! Специалисту по настройке не нужно ничего компилировать для предоставления доступа к этим объектам.


person Christian Findlay    schedule 15.01.2018    source источник


Ответы (1)


Это можно сделать с помощью Swashbuckle следующим образом:

public class SwaggerOperationFilter : IOperationFilter
{
    #region Fields
    private const string testpropertyname = "TestProperty";
    private const string TestSchemaRef = "ADef";
    private static Schema TestSchema = new Schema { Required = new List<string> { testpropertyname }, Example = new { TestProperty = "Test" }, Description = "This is a Description", Title = "TestSchema", Properties = new Dictionary<string, Schema>() };
    #endregion

    #region Static Constructor
    static SwaggerOperationFilter()
    {
        TestSchema.Properties.Add(testpropertyname, new Schema { Type = "string" });
    }
    #endregion

    #region Implementation
    public void Apply(Operation operation, OperationFilterContext context)
    {
        if (!context.SchemaRegistry.Definitions.ContainsKey(TestSchemaRef))
        {
            context.SchemaRegistry.Definitions.Add(TestSchemaRef, TestSchema);
        }

        operation.Responses["200"] = new Response
        {
            Description = "This is a Response Description",
            Schema = TestSchema
        };
    }
    #endregion
}
person Christian Findlay    schedule 17.01.2018