2013-03-29 56 views
4

我正在研究在WebApi中使用odata。到目前爲止這麼好,我喜歡那種更加靈活的wcf數據服務。WebApi OData實體集/鍵/導航/鍵支持

但是,當我嘗試在模型中使用虛擬IQueryable屬性時遇到問題。

因此,例如,我有這些模型類:

public class MainItem 
{ 
    public int Id { get; set;} 
    public virtual IEnumerable<SubItem> SubItems { get; set;} 
} 

而且我MainItemsController看起來像這樣

public class MainItemsController : EntitySetController<MainItem, int> 
{ 
    [Queryable] 
    public override IQueryable<MainItem> Get() 
    { 
     return SomeMainItemIQueryable(); 
    } 

    public override GetEntityByKey(int key) 
    { 
     return SingleMainItem(key); 
    } 

    [Queryable] 
    public IQueryable GetSubItems(int key) 
    { 
     return SomeSubItemIQueryable(SingleMainItem(key)); 
    } 
} 

我得到以下網址的正確的結果: /的OData/MainItems /OData的/ MainItems(1) /odata/MainItems(1)/ SubItems

但是,當我嘗試做 /的OData/MainItems(1)/子項(1)

我得到這個錯誤 此服務不支持的格式 '〜/ EntitySet的/鍵/導航/鍵'

我會的OData請求喜歡將此調用重定向到/ odata/MainItems(1)/ SubItems到SubItemsController。

我可以通過製作一個自定義的ODataPathHandler來做到這一點,但是這並不像這樣做的正確方式。

回答

5

沒錯。你不需要一個自定義的路徑處理程序。它代表我們瞭解的有效OData網址,並可將其解析爲ODataPath。你需要的是一個自定義路由約定。路由約定將ODataPath映射到控制器和操作。默認情況下,我們只提供處理WCF DS客戶端生成的URL的基本路由約定。看起來您正在使用我們沒有路由約定的網址。儘管寫一個很簡單。例如,

public class ContainmentRoutingConvention : IODataRoutingConvention 
{ 
    public string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap) 
    { 
     IEdmEntitySet entitySet = odataPath.EntitySet; 

     if (odataPath.PathTemplate == "~/entityset/key/navigation") 
     { 
      controllerContext.RouteData.Values["key"] = (odataPath.Segments[1] as KeyValuePathSegment).Value; 
      return "Get" + entitySet.Name; 
     } 
     else if (odataPath.PathTemplate == "~/entityset/key/navigation/key") 
     { 
      controllerContext.RouteData.Values["key1"] = (odataPath.Segments[1] as KeyValuePathSegment).Value; 
      controllerContext.RouteData.Values["key2"] = (odataPath.Segments[3] as KeyValuePathSegment).Value; 
      return "Get" + entitySet.ElementType.Name; 
     } 

     return null; 
    } 

    public string SelectController(ODataPath odataPath, HttpRequestMessage request) 
    { 
     if (odataPath.PathTemplate == "~/entityset/key/navigation" || 
      odataPath.PathTemplate == "~/entityset/key/navigation/key") 
     { 
      IEdmNavigationProperty navigationProperty = (odataPath.Segments[2] as NavigationPathSegment).NavigationProperty; 
      IEdmEntitySet entitySet = odataPath.EntitySet; // the target entity set, which would be 'SubItems'; 

      return entitySet.Name; 
     } 

     return null; 
    } 
} 

這隻會處理您提到的兩個網址。應該很容易擴展以支持其他網址。

處理〜/ entityset/key/navigation的操作的簽名將爲IEnumerable<Order> GetOrders(int key),url〜/ entityset/key/navigation/key將爲Order GetOrder(int key1, int key2)

+0

非常感謝! – Rolfvm