studio - swagger web api c#
Documentación de Swagger UI Web Api ¿Presenta enumeraciones como cadenas? (6)
¡Acabo de hacer esto y funciona bien!
Startup.cs
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
Model.cs
public enum ColumnType {
DATE = 0
}
swagger.json
type: {
enum: ["DATE"],
type: "string"
}
¡Espero que esto te ayude como me ayudó!
¿Hay alguna manera de mostrar todas las enumeraciones como su valor de cadena en swagger en lugar de su valor int?
Quiero poder enviar acciones POST y poner enumeraciones de acuerdo con su valor de cadena sin tener que mirar la enumeración cada vez.
Intenté
DescribeAllEnumsAsStrings
pero el servidor recibe cadenas en lugar del valor de enumeración que no es lo que estamos buscando.
¿Alguien ha resuelto esto?
Editar:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
public Priority Priority {get; set;}
}
public class LettersController : ApiController
{
[HttpPost]
public IHttpActionResult SendLetter(Letter letter)
{
// Validation not passing when using DescribeEnumsAsStrings
if (!ModelState.IsValid)
return BadRequest("Not valid")
..
}
// In the documentation for this request I want to see the string values of the enum before submitting: Low, Medium, High. Instead of 0, 1, 2
[HttpGet]
public IHttpActionResult GetByPriority (Priority priority)
{
}
}
public enum Priority
{
Low,
Medium,
High
}
De los documentos :
httpConfiguration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "A title for your API");
c.DescribeAllEnumsAsStrings(); // this will do the trick
});
Además, si desea este comportamiento solo en un tipo y propiedad en particular, use StringEnumConverter:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
[JsonConverter(typeof(StringEnumConverter))]
public Priority Priority {get; set;}
}
Entonces creo que tengo un problema similar. Estoy buscando swagger para generar enumeraciones junto con el mapeo de cadenas int ->. La API debe aceptar el int. El swagger-ui importa menos, lo que realmente quiero es la generación de código con una enumeración "real" en el otro lado (aplicaciones de Android que utilizan la modificación en este caso).
Entonces, según mi investigación, esto parece ser un límite de la especificación OpenAPI que Swagger usa. No es posible especificar nombres y números para enumeraciones.
El mejor problema que he encontrado para seguir es https://github.com/OAI/OpenAPI-Specification/issues/681 que parece un "tal vez pronto", pero luego Swagger tendría que actualizarse, y en mi caso Swashbuckle como bien.
Por ahora, mi solución ha sido implementar un filtro de documentos que busque enumeraciones y complete la descripción relevante con el contenido de la enumeración.
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.DocumentFilter<SwaggerAddEnumDescriptions>();
//disable this
//c.DescribeAllEnumsAsStrings()
SwaggerAddEnumDescriptions.cs:
using System;
using System.Web.Http.Description;
using Swashbuckle.Swagger;
using System.Collections.Generic;
public class SwaggerAddEnumDescriptions : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
// add enum descriptions to result models
foreach (KeyValuePair<string, Schema> schemaDictionaryItem in swaggerDoc.definitions)
{
Schema schema = schemaDictionaryItem.Value;
foreach (KeyValuePair<string, Schema> propertyDictionaryItem in schema.properties)
{
Schema property = propertyDictionaryItem.Value;
IList<object> propertyEnums = property.@enum;
if (propertyEnums != null && propertyEnums.Count > 0)
{
property.description += DescribeEnum(propertyEnums);
}
}
}
// add enum descriptions to input parameters
if (swaggerDoc.paths.Count > 0)
{
foreach (PathItem pathItem in swaggerDoc.paths.Values)
{
DescribeEnumParameters(pathItem.parameters);
// head, patch, options, delete left out
List<Operation> possibleParameterisedOperations = new List<Operation> { pathItem.get, pathItem.post, pathItem.put };
possibleParameterisedOperations.FindAll(x => x != null).ForEach(x => DescribeEnumParameters(x.parameters));
}
}
}
private void DescribeEnumParameters(IList<Parameter> parameters)
{
if (parameters != null)
{
foreach (Parameter param in parameters)
{
IList<object> paramEnums = param.@enum;
if (paramEnums != null && paramEnums.Count > 0)
{
param.description += DescribeEnum(paramEnums);
}
}
}
}
private string DescribeEnum(IList<object> enums)
{
List<string> enumDescriptions = new List<string>();
foreach (object enumOption in enums)
{
enumDescriptions.Add(string.Format("{0} = {1}", (int)enumOption, Enum.GetName(enumOption.GetType(), enumOption)));
}
return string.Join(", ", enumDescriptions.ToArray());
}
}
Esto da como resultado algo como lo siguiente en su swagger-ui para que al menos pueda "ver lo que está haciendo":
Quería usar la respuesta de rory_za en una aplicación .NET Core, pero tuve que modificarla un poco para que funcione. Aquí está la implementación que se me ocurrió para .NET Core.
También lo cambié para que no asuma que el tipo subyacente es
int
, y use nuevas líneas entre los valores para facilitar la lectura.
/// <summary>
/// Add enum value descriptions to Swagger
/// </summary>
public class EnumDocumentFilter : IDocumentFilter {
/// <inheritdoc />
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) {
// add enum descriptions to result models
foreach (var schemaDictionaryItem in swaggerDoc.Definitions) {
var schema = schemaDictionaryItem.Value;
foreach (var propertyDictionaryItem in schema.Properties) {
var property = propertyDictionaryItem.Value;
var propertyEnums = property.Enum;
if (propertyEnums != null && propertyEnums.Count > 0) {
property.Description += DescribeEnum(propertyEnums);
}
}
}
if (swaggerDoc.Paths.Count <= 0) return;
// add enum descriptions to input parameters
foreach (var pathItem in swaggerDoc.Paths.Values) {
DescribeEnumParameters(pathItem.Parameters);
// head, patch, options, delete left out
var possibleParameterisedOperations = new List<Operation> {pathItem.Get, pathItem.Post, pathItem.Put};
possibleParameterisedOperations.FindAll(x => x != null)
.ForEach(x => DescribeEnumParameters(x.Parameters));
}
}
private static void DescribeEnumParameters(IList<IParameter> parameters) {
if (parameters == null) return;
foreach (var param in parameters) {
if (param is NonBodyParameter nbParam && nbParam.Enum?.Any() == true) {
param.Description += DescribeEnum(nbParam.Enum);
} else if (param.Extensions.ContainsKey("enum") && param.Extensions["enum"] is IList<object> paramEnums &&
paramEnums.Count > 0) {
param.Description += DescribeEnum(paramEnums);
}
}
}
private static string DescribeEnum(IEnumerable<object> enums) {
var enumDescriptions = new List<string>();
Type type = null;
foreach (var enumOption in enums) {
if (type == null) type = enumOption.GetType();
enumDescriptions.Add($"{Convert.ChangeType(enumOption, type.GetEnumUnderlyingType())} = {Enum.GetName(type, enumOption)}");
}
return $"{Environment.NewLine}{string.Join(Environment.NewLine, enumDescriptions)}";
}
}
Luego agregue esto a su método
ConfigureServices
en Startup.cs:
c.DocumentFilter<EnumDocumentFilter>();
escribir código dentro de Startup.cs
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
DescribeAllEnumsAsStrings()
no funcionó para mí porque entonces, como OP dijo, el servidor recibe cadenas y espera ints.
Para permitir que el servidor espere cadenas, creo que necesita agregar StringEnumConverter a SerializerSettings, además de que puede dejar DescribeAllEnumsAsStrings () por completo.
tl; dr: solo haz esto en Startup.cs / ConfigureServices ():
services
.AddMvc(...)
.AddJsonOptions(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()));