【问题标题】:How to force a WebAPI OData expand clause?如何强制使用 WebAPI OData 扩展子句?
【发布时间】:2014-08-01 18:42:56
【问题描述】:

如果我有以下自定义模型/DTO,则使用 Microsoft WebAPI OData 版本 5.6 (OData v3):

public class ParentObject
{
  public int ID { get; set; }
  public string Title {get; set;}
  public ChildObject Child { get; set;}
}  

public class ChildObject
{
  public string Value { get; set;}
}

以及将我的数据库投影到模型中的以下控制器:

public class ParentsController : ODataController
{
  public IQueryable<ParentObject> Get()
  {
    var db = new MyDBContext();
    var results = from p in db.parent
                  select new ParentObject
                  {
                    ID = p.id,
                    Title = p.title,
                    Child = p.child == null ? null : new ChildObject 
                    {
                      Value = p.child.value
                    }
                   };

    return results;
   }
  }
} 

如何强制展开“Child”而不需要消费者在 url 中指定 $expand=Child?

我想:
1. 检查消费者是否已经指定了 $expand=Child
2. 如果“子”尚未包含在展开列表中,则将其包含。
3. 确保尊重任何其他查询选项

我查看了几篇我不清楚或引用不再匹配的旧版本 api 的在线文章。

我尝试将 Action 修改为“Get(ODataQueryOptions opts)”,这让我可以执行以下操作:

if(opts.SelectExpand == null || !opts.SelectExpand.RawExpand.Contains("Child"))
{
  // Add/modify expand clause here.
}

但是我不清楚如何修改或构建我自己的 ODataQueryOptions 对象,维护所有其他查询选项,然后将其应用于结果。

更新 1

我已经取得了一些进展。下面是控制器的相关改动(dbcontext查询同上):

public PageResult<ParentObject> Get(ODataQueryOptions opts)
{
 SelectExpandQueryOption expandOpts = null;
 if(opts.SelectExpand != null && !opts.SelectExpand.RawExpand.Contains("Child"))
 {
  expandOpts = new SelectExpandQueryOption(opts.SelectExpand.RawSelect, string.Join(",", new string[] {"Child", opts.SelectExpand.RawExpand }), opts.Context);
 }
 else if (opts.SelectExpand == null)
 {
  expandOpts = new SelectExpandQueryOption(null, "Child", opts.Context);
 }

 // Query from above goes here

 if(expandOpts != null)
 {
  Request.SetSelectExpandClause(expandOpts.SelectExpandClause);
 }

 var qSettings = new ODataQuerySettings();
 qSettings.PageSize = 100;

 results = opts.ApplyTo(results, qSettings).AsQueryable() as IQueryable<ParentObject>;
 return new PageResult<ParentObject>(results, Request.GetNextPageLink(), Request.GetInlineCount());
}

当我不包含“$expand”查询选项(创建了expandOpts)时,这似乎工作正常。但是,当存在“$expand”时,我在 return 语句上得到一个 ArgumentNullExcpetion 并且无法弄清楚原因。

【问题讨论】:

  • 你的技术也对我有用。您应该将其作为答案并将其标记为已接受。唯一的区别是 Request.SetSelectExpandClause 已过时,所以我改用 Request.ODataProperties().SelectExpandClause 属性

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


【解决方案1】:

我自己花了几个小时后,这就是答案。您需要设置扩展字符串并执行包含以使其正常工作。

[EnableQuery]
public IQueryable<Student> Get_Student(ODataQueryOptions<Student> queryOptions)
{
var db = new EfCustomAdapter();

var  expandOpts = new SelectExpandQueryOption(null, "Parent,Schools", queryOptions.Context);
var q = db.Student.AsQueryable();
q = q.Include(t => t.Parent);
q = q.Include(t => t.Schools);
queryOptions.Request.ODataProperties().SelectExpandClause = expandOpts.SelectExpandClause;
return q;
}

更新: 如果您需要在语法下方扩展级别是.. “父母、学校、账单/付款”

支付对象是账单的导航属性。

【讨论】:

  • 谢谢,这真的很有用!不过我注意到,如果还使用了 $select odata 查询选项,那么这段代码会替换它吗?我试过拉 $select 选项并作为 SelectExpandQueryOption() 构造函数的第一个参数传递。如果新的扩展选项不验证原始选择选项,这会产生奇怪的副作用。
【解决方案2】:

看看底部附近:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options。 MyQueryableAttribute 可能是您需要的。您可以创建一个自定义 QueryableWithChildAttribute 类,该类注入您需要的 queryOptions.Expand。然后,只需使用[QueryableWithChild()] 装饰您的方法。

希望这会有所帮助。

【讨论】:

  • 虽然这不是答案,我看了这个页面 100 次,但你不知怎的让我走上了正确的道路,所以我会接受这个作为答案并更新我的帖子。
  • 我以为我有这个工作,但它还没有完全工作。必须不接受,并将随着进度更新问题。对不起:(
猜你喜欢
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
相关资源
最近更新 更多