у меня есть этот контроллер
public class Person
{
public int Id { get; set; }
public string Position { get; set; }
}
[ApiController]
[Route("[controller]")]
public class MyCtrl : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<Person> Get(int id)
{
// load person with ID == id from db
return new ActionResult<Person>(person);
}
}
Теперь Position — это просто строка, но в зависимости от конфигурации в базе данных это может быть только набор конечных значений. Мне бы очень хотелось, чтобы я мог имитировать то, что Position было перечислением в интерфейсе Swagger (я использую NSwag).
Мне бы хотелось, чтобы API выглядел так, как будто он был создан на основе этого (где PositionType генерируется из конфигурации в БД):
public enum PositionType
{
Student,
Teacher
}
public class Person
{
public int Id { get; set; }
public PositionType Position { get; set; }
}





В итоге я сделал это.
[AttributeUsage(AttributeTargets.Property)]
public class PositionEnum : Attribute
{
}
public class Person
{
public int Id { get; set; }
[PositionEnum]
public string Position { get; set; }
}
public class PositionEnumProcessor : ISchemaProcessor
{
public void Process(SchemaProcessorContext context)
{
var propertyInfos =
context.ContextualType.Properties
.Where(x => Attribute.IsDefined(x.PropertyInfo, typeof(PositionEnum)))
.ToList();
if (!propertyInfos.Any())
{
return;
}
var jsonSchema = context.Generator.Generate(typeof(PositionType), context.Resolver);
var containerSchema = JsonSchema.FromType<object>();
containerSchema.Type = JsonObjectType.None;
containerSchema.Reference = jsonSchema;
foreach (var propertyInfo in propertyInfos)
{
var camelCasePropertyName = System.Text.Json.JsonNamingPolicy.CamelCase.ConvertName(propertyInfo.Name);
if (context.Schema.Properties.TryGetValue(camelCasePropertyName, out var schemaProperty))
{
schemaProperty.Type = JsonObjectType.None;
schemaProperty.OneOf.Add(containerSchema);
}
}
}
}
Затем в builder.Services.AddOpenApiDocument() я добавил это:
...
openApiConfiguration.SchemaSettings.SchemaProcessors.Add(new PositionEnumProcessor());
...
Если у кого-то есть более элегантное решение, дайте мне знать 😊
Не уверен, что это полезно github.com/RicoSuter/NSwag/issues/3321 — проблема все еще открыта