加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

.net – WebApi OData实体集/密钥/导航/密钥支持

发布时间:2020-12-16 06:26:29 所属栏目:asp.Net 来源:网络整理
导读:我正在研究在WebApi中使用odata.到目前为止这么好,我喜欢它比wcf数据服务更灵活. 但是当我尝试在模型中使用虚拟IQueryable属性时遇到问题. 所以例如我有这些模型类: public class MainItem{ public int Id { get; set;} public virtual IEnumerableSubItem
我正在研究在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));
    }
}

我在以下网址上得到了正确的结果:
????/的OData / MainItems
????/的OData / MainItems(1)
????/的OData / MainItems(1)/子项目

但是当我尝试做的时候
????/的OData / MainItems(1)/子项(1)

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

我很乐意将此调用以及/ odata / MainItems(1)/ SubItems重定向到SubItemsController.

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

解决方法

那就对了.您不需要自定义路径处理程序.它表示我们理解的有效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;
    }
}

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

处理?/ entityset / key / navigation的动作的签名将是IEnumerable< Order> GetOrders(int key)和url~ / entityset / key / navigation / key,它将是Order GetOrder(int key1,int key2).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读