【问题标题】:Reconstructing an ODataQueryOptions object and GetInlineCount returning null重建 ODataQueryOptions 对象和 GetInlineCount 返回 null
【发布时间】:2013-08-14 08:35:17
【问题描述】:

在返回 PageResult 的 odata webapi 调用中,我从方法参数中提取 requestUri,操作过滤条件,然后使用新的 uri 构造一个新的 ODataQueryOptions 对象。

(PageResult 方法基于这篇文章: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options)

这是包含 %24inlinecount=allpages 的原始入站 uri

http://localhost:59459/api/apiOrders/?%24filter=OrderStatusName+eq+'Started'&filterLogic=AND&%24skip=0&%24top=10&%24inlinecount=allpages&_=1376341370337

就返回的数据而言,一切正常,除了 Request.GetInLineCount 返回 null。

由于客户端 ui 元素不知道记录的总数,因此在客户端“杀死”分页。

我构造新 ODataQueryOptions 对象的方式一定有问题。

请在下面查看我的代码。任何帮助,将不胜感激。

我怀疑这篇文章可能包含一些线索https://stackoverflow.com/a/16361875/1433194,但我很难过。

public PageResult<OrderVm> Get(ODataQueryOptions<OrderVm> options)
    {

        var incomingUri = options.Request.RequestUri.AbsoluteUri;

//manipulate the uri here to suit the entity model   
//(related to a transformation needed for enumerable type OrderStatusId )
//e.g. the query string may include %24filter=OrderStatusName+eq+'Started' 
//I manipulate this to %24filter=OrderStatusId+eq+'Started'

        ODataQueryOptions<OrderVm> options2;

        var newUri = incomingUri;  //pretend it was manipulated as above

        //Reconstruct the ODataQueryOptions with the modified Uri

        var request = new HttpRequestMessage(HttpMethod.Get, newUri);

        //construct a new options object using the new request object
        options2 = new ODataQueryOptions<OrderVm>(options.Context, request);

        //Extract a queryable from the repository.  contents is an IQueryable<Order>
        var contents = _unitOfWork.OrderRepository.Get(null, o => o.OrderByDescending(c => c.OrderId), "");

        //project it onto the view model to be used in a grid for display purposes
        //the following projections etc work fine and do not interfere with GetInlineCount if
        //I avoid the step of constructing and using a new options object
        var ds = contents.Select(o => new OrderVm
        {
            OrderId = o.OrderId,
            OrderCode = o.OrderCode,
            CustomerId = o.CustomerId,
            AmountCharged = o.AmountCharged,
            CustomerName = o.Customer.FirstName + " " + o.Customer.LastName,
            Donation = o.Donation,
            OrderDate = o.OrderDate,
            OrderStatusId = o.StatusId,
            OrderStatusName = ""
        });

        //note the use of 'options2' here replacing the original 'options'
        var settings = new ODataQuerySettings()
        {
            PageSize = options2.Top != null ? options2.Top.Value : 5
        };

        //apply the odata transformation
        //note the use of 'options2' here replacing the original 'options'    
        IQueryable results = options2.ApplyTo(ds, settings);

        //Update the field containing the string representation of the enum
        foreach (OrderVm row in results)
        {
            row.OrderStatusName = row.OrderStatusId.ToString();
        }

        //get the total number of records in the result set 
        //THIS RETURNS NULL WHEN USING the 'options2' object - THIS IS MY PROBLEM
        var count = Request.GetInlineCount();

        //create the PageResult object
        var pr = new PageResult<OrderVm>(
            results as IEnumerable<OrderVm>,
            Request.GetNextPageLink(),
            count
            );
        return pr;
    }

编辑
所以更正后的代码应该是

//create the PageResult object
var pr = new PageResult<OrderVm>(
    results as IEnumerable<OrderVm>,
    request.GetNextPageLink(),
    request.GetInlineCount();
    );
return pr;

编辑
通过对 OrderVm 类的 OrderStatusId 属性(一个枚举)应用 Json 转换,避免了在控制器方法中对枚举进行字符串转换

[JsonConverter(typeof(StringEnumConverter))]
public OrderStatus OrderStatusId { get; set; }

这消除了 foreach 循环。

【问题讨论】:

  • 除了查询\分页之外,您是否使用 OData 支持?如果不是,则考虑使用 Linq to Querystring 作为 Web API 产品的替代方案,如对以下问题的回答:stackoverflow.com/questions/17971798/… Web API OData 不支持开箱即用的 DTO 投影,因此您可能会看到一些不可预测的行为,而您粘贴的代码有很多不必要的复杂性!
  • 谢谢@roysvork 我会检查一下。我在客户端使用 infragistics igniteui 网格和数据源。 http://help.infragistics.com/jQuery/2013.1/ 看起来 Linq to Querystring 可以正常工作。我会回来报告的。
  • 我发现 Infragistics igniteui 网格使用 LinqToQueryable 属性使用来自 web-api 方法的数据。但是,我希望能够操纵查询服务器端来处理枚举的过滤和排序,其中客户端呈现枚举的字符串表示形式。或者,我确信有更好的方法来处理枚举。

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


【解决方案1】:

仅当客户端通过$inlinecount 查询选项请求它时才会出现InlineCount。

在您的修改 uri 逻辑中添加查询选项 $inlinecount=allpages(如果它尚不存在)。

另外,您的代码中有一个小错误。您正在创建的新 ODataQueryOptions 使用新的 request,而在 GetInlineCount 调用中,您使用的是旧的 Request。它们不一样。

应该是,

var count = request.GetInlineCount(); // use the new request that your created, as that is what you applied the query to.

【讨论】:

  • $inlinecount=allpages 存在于原始和修改后的 uri 中
  • 您正在对request 应用查询并尝试从Request 读取InlineCount。局部变量与类属性。我已经更新了答案以包括这个。
  • 谢谢@RaghuRamNadiminti。使用局部变量request 代替类Request 解决了这个问题。
  • 同样的解决方案适用于GetNextPageLink() 它应该是request.GetNextPageLink(),而不是Request.GetNexPageLink()
猜你喜欢
  • 1970-01-01
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 2022-01-25
  • 2021-05-17
  • 1970-01-01
相关资源
最近更新 更多