无法通过OData的SelectExpandClause覆盖SelectExpand功能的问题求助
嘿,看起来你在手动覆盖OData的SelectExpandClause时踩坑了,我来帮你捋捋可能的问题点和调整思路:
首先,你构建SelectExpandQueryOption的方式有问题
你现在用new SelectExpandQueryOption(null, "Foo", options.Context, queryOptionParser)的参数逻辑不对。这个构造函数的前两个参数分别对应$select和$expand的原始查询字符串,你第一个参数传null相当于没有指定$select,第二个传"Foo"是指定$expand=Foo,但你同时又在queryOptionParser里传了包含$expand的字典,这就造成了重复定义,OData可能不知道该用哪个。其实完全不需要手动实例化ODataQueryOptionParser,直接用上下文和查询字符串来创建SelectExpandQueryOption就行。其次,你给ODataFeature赋值的时机可能不对
你直接给options.Request.ODataFeature().SelectExpandClause赋值,但有时候ODataFeature可能还没完成初始化,或者你应该在构建ODataQueryOptions的阶段就把自定义的select/expand逻辑注入进去,而不是事后修改。结合用户角色的需求,我给你个更合理的实现思路
你不用硬编码"Foo",而是先基于用户角色和实体上的权限属性,过滤出用户有权访问的字段和可展开的关联,再和请求里的$select/$expand参数合并,得到最终的允许列表,再用这个列表来构建正确的SelectExpandQueryOption。示例代码如下:// 先实现两个方法,根据用户角色获取允许的字段和关联 var allowedSelectFields = GetAllowedSelectFields<T>(currentUser); var allowedExpandRelations = GetAllowedExpandRelations<T>(currentUser); // 从请求里获取原始的$select和$expand参数 var rawSelect = options.Context.Request.Query["$select"].ToString(); var rawExpand = options.Context.Request.Query["$expand"].ToString(); // 合并原始参数和权限允许的列表,只保留交集;如果请求无参数则直接用权限允许的全部内容 var finalSelect = string.Join(",", !string.IsNullOrEmpty(rawSelect) ? rawSelect.Split(',').Intersect(allowedSelectFields) : allowedSelectFields); var finalExpand = string.Join(",", !string.IsNullOrEmpty(rawExpand) ? rawExpand.Split(',').Intersect(allowedExpandRelations) : allowedExpandRelations); // 用最终的参数构建SelectExpandQueryOption var selectExpandOption = new SelectExpandQueryOption(finalSelect, finalExpand, options.Context); // 把生成的SelectExpandClause赋值给ODataFeature var odataFeature = options.Request.ODataFeature(); odataFeature.SelectExpandClause = selectExpandOption.SelectExpandClause; // 应用到查询并返回 var projected = options.ApplyTo(query) as IQueryable<dynamic>; return projected;这样既尊重了请求里的
$select/$expand参数,又通过角色权限做了过滤,完美匹配你的需求。最后,还有几个小细节要注意
- 你初始化ODataQueryOptions的时候,每次都新建ODataConventionModelBuilder可能会导致模型不一致,建议复用全局的EdmModel实例
- 尽量避免直接转成
IQueryable<dynamic>,能用强类型的IQueryable就用强类型,减少动态类型带来的投影异常 - 测试的时候先去掉角色控制的逻辑,先让基础的select/expand功能正常生效,确认没问题后再叠加权限过滤的逻辑
内容来源于stack exchange

