【问题标题】:Modifying response content returned from ASP.NET Web API using OData QueryableAttribute使用 OData QueryableAttribute 修改从 ASP.NET Web API 返回的响应内容
【发布时间】:2013-11-03 08:22:15
【问题描述】:

这是我的问题。我正在使用 ASP.NET Web API 2.0 和 QueryableAttribute 来利用一些 OData 过滤功能。

public class VideoController : ApiController
{
    [HttpGet]
    [Route("activevideos")]
    [Queryable]
    public IEnumerable<Video> GetActiveVideos(ODataQueryOptions<Video> options)
    {
        return new GetvContext().Videos.Where(c => c.IsActive);
    }        
}

现在,我有一个类用于修改响应对象和包含的实体。这在我开始使用 QueryableAttribute 之前工作正常。在此之前,我从前一个方法返回一个 List 而不是 IEnumerable。

public class TestMessageProcessHandler : MessageProcessingHandler
{
    protected override HttpResponseMessage ProcessResponse(
        HttpResponseMessage response, CancellationToken cancellationToken)
    {

        var content = ((ObjectContent)(response.Content)).Value;
        // Do something here with the content.  This used to be a List<Video> 
        // but now the object it is of type: 
        // System.Data.Entity.Infrastructure.DbQuery<System.Web.Http.OData.Query.Expressions.SelectExpandBinder.SelectSome<Content.Api.Video>>
    }
}

我需要能够从中获取实体,但我不确定如何从类型中获取:

System.Data.Entity.Infrastructure.DbQuery&lt;System.Web.Http.OData.Query.Expressions.SelectExpandBinder.SelectSome&lt;Content.Api.Video&gt;&gt; 改成List&lt;Video&gt; 这样我就可以修改Video 对象。

【问题讨论】:

  • 我完全没有使用 OData 的经验,所以我在这里可能完全错了,但 GetActiveVideos 方法不应该返回 IQueryable&lt;Video&gt; 而不是 IEnumerable&lt;Video&gt; 吗?尽管 OData 可能能够对其进行查询,但它不会限制从数据库返回的记录数。

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


【解决方案1】:

删除[Queryable] 属性并自行管理数据查询 - 如下所示:

public class VideoController : ApiController
{
    [HttpGet]
    [Route("activevideos")]
    public IList<Video> GetActiveVideos(ODataQueryOptions<Video> options)
    {
        var s = new ODataQuerySettings() { PageSize = 1 };
        var result = options.ApplyTo(
            new GetvContext().Videos.Where(c => c.IsActive), s)
            .ToList();

        return result;
    }        
}

【讨论】:

  • 一个问题是对从options.ApplyTo() 返回的对象调用 ToList() 将无法编译。无法推断类型参数。我也不能这样做:var result = options.ApplyTo(new GetvContext().Videos.Where(c =&gt; c.IsActive), s).AsQueryable().Cast&lt;Video&gt;().ToList(); 因为它无法转换类型为 'SelectSome'1[Content.Api.Video]' to type 'Content.Api.Video' 的对象(SelectSome 是 OData 库中的私有类)
  • 另一个问题是我实际上是在扩展 QueryableAttribute 以绕过其他一些 OData 特性。如果我可以使用您的方法的变体并且如果真的没有其他选择,我会使用它,但我真的不希望对我拥有的每一个 API 操作都这样做。
【解决方案2】:

你不能只做一个 ToList() - DbQuery 实现 IQueryable...

例如

var content = ((ObjectContent)(response.Content)).Value;
var queryable = content as IQueryable<Video>;
var list = queryable.ToList();

【讨论】:

    【解决方案3】:

    您很可能遇到此问题,因为您指定了 OData 查询应选择哪些字段(例如,$select=Nr,Date)。如果您不这样做,在应用查询选项后,OData 将不会返回 SelectSome 对象,它将返回您正在查询的相同对象,在您的情况下为 Video。因此,您可以轻松地在服务器端修改这些对象,然后再将它们返回给客户端。

    如果您需要从 Video 对象中排除您不需要的属性,而不是 $select 查询选项,您可以使用 DTO 代替您的 Video 对象,并且仅在此 DTO 中包含您需要。

    是的,这是一种解决方法,希望在这个库的未来版本中会有更好的方法来处理服务器端逻辑

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-09
      • 2015-10-15
      • 2014-10-07
      • 2015-10-23
      • 2014-10-18
      • 2015-12-27
      • 2019-11-10
      • 1970-01-01
      相关资源
      最近更新 更多