【问题标题】:WebApi OData entityset/key/navigation/key supportWebApi OData 实体集/键/导航/键支持
【发布时间】:2013-03-20 03:08:27
【问题描述】:

我正在研究在 WebApi 中使用 odata。到目前为止一切顺利,我喜欢它比 wcf 数据服务更灵活。

但是,当我尝试在模型中使用虚拟 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));
    }
}

我在以下 url 上得到了正确的结果: /odata/MainItems /odata/MainItems(1) /odata/MainItems(1)/SubItems

但是当我尝试做 /odata/MainItems(1)/SubItems(1)

我收到此错误 此服务不支持“~/entityset/key/navigation/key”形式的 OData 请求

我希望将此调用以及 /odata/MainItems(1)/SubItems 重定向到 SubItemsController。

我可能可以通过制作自定义 ODataPathHandler 来做到这一点,但这感觉不是正确的做法。

【问题讨论】:

    标签: .net c#-4.0 asp.net-web-api odata


    【解决方案1】:

    没错。您不需要自定义路径处理程序。它表示我们理解的有效 OData URL,可以将其解析为 ODataPath。您需要的是自定义路由约定。路由约定将 ODataPath 映射到控制器和操作。默认情况下,我们仅提供处理 WCF DS 客户端生成的 url 的基本路由约定。看起来您正在使用我们没有路由约定的 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;
        }
    }
    

    这只会处理您提到的两个网址。它应该很容易扩展以支持其他 url。

    处理 ~/entityset/key/navigation 的操作的签名将是 IEnumerable&lt;Order&gt; GetOrders(int key),对于 url ~/entityset/key/navigation/key,它将是 Order GetOrder(int key1, int key2)

    【讨论】:

      猜你喜欢
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2013-06-02
      • 2015-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多