ApiExplorer no reconoce los atributos de ruta con un tipo personalizado

Tengo un proyecto en el que quiero usar atributos de ruta con un tipo personalizado. El siguiente código donde tengo el tipo personalizado como parámetro de consulta funciona bien y la página de ayuda muestra el tipo personalizado.

// GET api/values?5,6 [Route("api/values")] public string Get(IntegerListParameter ids) { return "value"; } 

WebApi.HelpPage proporciona la siguiente documentación Ayuda: Página

Si cambio el código para usar atributos de ruta, el resultado es que obtengo una página de ayuda vacía.

 // GET api/values/5,6 [Route("api/values/{ids}")] public string Get(IntegerListParameter ids) { return "value"; } 

Cuando inspecciono el código que observo en HelpController.cs, ApiExplorer.ApiDescriptions devuelve una colección vacía de ApiDescriptions

 public ActionResult Index() { ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider(); Collection apiDescriptions = Configuration.Services.GetApiExplorer().ApiDescriptions; return View(apiDescriptions); } 

¿Hay alguna forma de hacer que ApiExplorer reconozca mi clase personalizada IntegerListParameter como enrutamiento de atributos?

Necesitas:

  1. agregue HttpParameterBinding para su tipo IntegerListParameter
  2. marque el enlace como IValueProviderParameterBinding e implemente ValueProviderFactories
  3. agregue un convertidor para IntegerListParameter y anule el método CanConvertFrom para el parámetro tipo typeof(string)

Después de estas acciones, la ruta con el tipo personalizado IntegerListParameter debe reconocerse en ApiExplorer.

Ver mi ejemplo para el tipo ObjectId :

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { //... config.ParameterBindingRules.Insert(0, GetCustomParameterBinding); TypeDescriptor.AddAttributes(typeof(ObjectId), new TypeConverterAttribute(typeof(ObjectIdConverter))); //... } public static HttpParameterBinding GetCustomParameterBinding(HttpParameterDescriptor descriptor) { if (descriptor.ParameterType == typeof(ObjectId)) { return new ObjectIdParameterBinding(descriptor); } // any other types, let the default parameter binding handle return null; } } public class ObjectIdParameterBinding : HttpParameterBinding, IValueProviderParameterBinding { public ObjectIdParameterBinding(HttpParameterDescriptor desc) : base(desc) { } public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) { try { SetValue(actionContext, new ObjectId(actionContext.ControllerContext.RouteData.Values[Descriptor.ParameterName] as string)); return Task.CompletedTask; } catch (FormatException) { throw new BadRequestException("Invalid id format"); } } public IEnumerable ValueProviderFactories { get; } = new[] { new QueryStringValueProviderFactory() }; } public class ObjectIdConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) return true; return base.CanConvertFrom(context, sourceType); } } 

No sé exactamente qué estructura de datos es la lista de IntegerListParameter pero si necesita enviar una lista de enteros delimitada por comas (por ejemplo, ~api/products?ids=1,2,3,4 ) puede usar los atributos de filtro. Puede encontrar un ejemplo de implementación de esto aquí: ¿ Convertir el filtro de acción personalizado para el uso de la API web?

    Intereting Posts