2016-12-16 130 views
1

我有一个项目,我想使用自定义类型的路由属性。 以下代码中,我将自定义类型作为查询参数运行正常,并且帮助页面显示自定义类型。ApiExplorer不识别自定义类型的路由属性

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

WebApi.HelpPage提供了以下文件 Help:Page

如果我改变使用路由属性的代码,结果是我得到一个空的帮助页面。

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

当我检查我在HelpController.cs观察代码ApiExplorer.ApiDescriptions返回ApiDescriptions的空收集

public ActionResult Index() 
{ 
    ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider(); 
    Collection<ApiDescription> apiDescriptions = Configuration.Services.GetApiExplorer().ApiDescriptions; 

    return View(apiDescriptions); 
} 

有没有什么办法让ApiExplorer认识到我的自定义类IntegerListParameter作为属性路由?

回答

0

不完全确定哪个数据结构是IntegerListParameter列表,但是如果需要在查询中发送逗号分隔的整数列表(例如~api/products?ids=1,2,3,4),则可以使用过滤器属性。这方面的例子实施可以在这里找到:Convert custom action filter for Web API use?

+0

我已经实现了用逗号分隔的整数列表。它可以很好地作为查询参数和属性路由。 –

+0

我的问题是,helppage没有显示列表是属性路由的行为。 问题是,当列表实现为属性路由时,ApiExplorer.ApiDescriptions不会识别该操作。 –

0

您需要:

  1. 添加HttpParameterBinding您IntegerListParameter
  2. 标记为IValueProviderParameterBinding的约束力和执行ValueProviderFactories
  3. 添加一个转换器,用于IntegerListParameter并覆盖CanConvertFrom方法typeof(string)参数

执行这些操作后,必须在ApiExplorer中识别具有自定义类型IntegerListParameter的路由。

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<ValueProviderFactory> 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); 
    } 
}