【问题标题】:How do I use OData $filter results on the server如何在服务器上使用 OData $filter 结果
【发布时间】:2016-04-13 06:38:17
【问题描述】:

我有一个正常工作的 OData 控制器,它支持所有正常的 get/put 等。

我要做的是从客户端传递一个普通的 odata $filter 字符串,在服务器上解析并执行过滤器,然后在生成的 IEnumerable 上运行一些代码。

我已经搞砸了 ODataQueryContext、ODataQueryOptions、FilterQueryOption 等,但没有真正得到任何地方。

有人有任何工作示例吗?

编辑:我已经添加了我的功能骨架,只需要填写空白

    public HttpResponseMessage GetJobs(string filter)
    {
        *** How to convert the filter into IQueryable<Job> ***
        var queryable = ?????    

        var settings = new ODataQuerySettings();
        var jobs = queryOptions.ApplyTo(querable, settings) as IQueryable<Job>;

        CsvSerializer csvSerializer = new CsvSerializer();
        string csv = csvSerializer.Serialise(jobs);
        string fileName = string.Format("{0} Jobs.csv", filter);
        return CreateCsvResponseMessage(csv, fileName);
    }

【问题讨论】:

    标签: odata


    【解决方案1】:

    我最近遇到了一个我也需要这种功能的场景。这就是我想出的。

        private static IQueryable<T> ApplyODataFilter<T>(IQueryable<T> data, string filterString) where T : class
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<T>(typeof(T).Name);
    
            ODataQueryContext context = new ODataQueryContext(builder.GetEdmModel(), typeof(T), new ODataPath());
    
            ODataQueryOptionParser queryOptionParser = new ODataQueryOptionParser(
                context.Model,
                context.ElementType,
                context.NavigationSource,
                new Dictionary<string, string> { { "$filter", filterString } });
    
            FilterQueryOption filter = new FilterQueryOption(filterString, context, queryOptionParser);
    
            IQueryable query2 = filter.ApplyTo(data, new ODataQuerySettings());
            return query2.Cast<T>();
        }
    

    【讨论】:

      【解决方案2】:

      尝试使用 OData 代码生成器生成客户端代码。您可以关注以下博客: How to use OData Client Code Generator to generate client-side proxy class

      对于过滤器,下面是一个例子:

      var q2 = TestClientContext.CreateQuery&lt;Type&gt;("Accounts").Where(acct =&gt; acct.Birthday &gt; new DateTimeOffset(new DateTime(2013, 10, 1)));

      【讨论】:

      • 我的过滤器是一个 odata 过滤器,比如“IncidentId eq 5”,所以我认为这个解决方案不会有帮助。
      • linq 代码将被翻译为 OData url,传递到服务器端。那么,您希望根据响应在客户端执行查询吗?
      • 没有。我想将 odata 查询传递给服务器,在服务器上执行它,并在服务器上使用 IEnumerable 结果。来自客户端的唯一部分是字符串“$filter=Incident eq 5”
      【解决方案3】:

      codeplex 中有一些示例代码来展示如何进行查询。

      检查一下:

      https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v3/ODataQueryableSample/Program.cs


      更新:

      我给你的示例的控制器中有一些示例代码。

      编写如下代码:

      public IQueryable<Order> Get(ODataQueryOptions queryOptions)
      {
          if (queryOptions.Filter != null)
          {
              var settings = new ODataQuerySettings();
              var filterResult = queryOptions.ApplyTo(OrderList.AsQueryable(), settings) as IQueryable<Order>;
              // Use the filter result here.
          }
      }
      

      更新 2: 您可以从 ODataQueryOptions 获取过滤器的原始字符串。

          public IQueryable<Order> Get(ODataQueryOptions queryOptions)
          {
              string filterString = queryOptions.Filter.RawValue;
              // Use the filterString
          }
      

      更新 3:

      (注意:ODataProperties 是静态类中的扩展方法 System.Web.Http.OData.Extensions.HttpRequestMessageExtensions

              public HttpResponseMessage GetJobs(string filter)
              {
                  var context = new ODataQueryContext(Request.ODataProperties().Model, typeof(Job));
                  var filterQueryOption = new FilterQueryOption(filter, context);
      
                  IQueryable<Job> queryable = GetAllJobs();
                  var settings = new ODataQuerySettings();
                  var jobs = filterQueryOption.ApplyTo(queryable, settings) as IQueryable<Job>;
      
                  CsvSerializer csvSerializer = new CsvSerializer();
                  string csv = csvSerializer.Serialise(jobs);
                  string fileName = string.Format("{0} Jobs.csv", filter);
                  return CreateCsvResponseMessage(csv, fileName);
              }
      

      【讨论】:

      • 谢谢冯,但这不是我所追求的。我不想要 HttpResponseMessage,因为那时我必须从 HTTP/odata 解析它。我只想要过滤器给出的元素列表。
      • 我已经编辑了我的问题以显示我在哪里遇到了困难。如何从过滤器字符串中获取 IQueryable?
      • 我发布了另一个更新来展示如何从 ODataQueryOptions 获取过滤器的原始字符串。(注意:queryOptions.Filter 可以为 null)
      • 嗨冯,我已经有了原始字符串,但我没有过滤器!我已经编辑了问题以使事情更清楚。
      • 您想要的是将过滤器原始字符串转换为 FilterQueryOption,而不是 IQueryable。检查我的更新。
      猜你喜欢
      • 2016-02-13
      • 1970-01-01
      • 2013-06-09
      • 1970-01-01
      • 2013-07-14
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多