2016-12-16 55 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); 
    } 
}