OData v4中的系统查询选项$ filter(规范函数)

时间:2014-12-19 14:51:40

标签: asp.net-web-api filter odata

根据此文档:http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part2-url-conventions/odata-v4.0-errata02-os-part2-url-conventions-complete.html#_Toc406398094 我应该能够传递$ filter参数查询,例如“$ filter = contains(PropertyName,'SomeValue')”。

当我传递逻辑运算符时(例如: $ filter = PropertyName eq'TomeValue')它工作正常。但是'contains','substring','endswith','startswith'等函数从不起作用 - 将ODataQueryOptions应用于DbSet的查询结果总是空集。

任何想法为什么?

2 个答案:

答案 0 :(得分:2)

所以你的意思是$ filter = contains(PropertyName,' SomeValue')不适合你的服务?该功能本身可以正常使用,请尝试使用http://services.odata.org/TripPinWebApiService/People?$ filter = contains(FirstName,' Angel')。如果您显示代码的更多详细信息,它将帮助其他人解决您的问题。您可以https://github.com/OData/ODataSamples/tree/master/Scenarios/TripPin查看OData V4示例服务的实现,或转到http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/ODataQueryableSample/了解Queryable和$ filter的工作原理。

由于您没有发布您的代码,我不确定问题是什么,我只是快速实施并且$ filter可以正常运行。希望能有所帮助。

Person的模型类

public class Person
    {
        [Key]
        public String ID { get; set; }

        [Required]
        public String FirstName { get; set; }

        [Required]
        public String LastName { get; set; }

        [Required]
        public int Age { get; set; }

        public String Description { get; set; }
    }

PeopleController.cs

[EnableQuery]
public class PeopleController : ODataController
{
    public IHttpActionResult Get()
    {
        return Ok(DemoDataSources.Instance.People.AsQueryable());
    }
}

WebApiConfig.cs

   public static class WebApiConfig
    {

        public static void Register(HttpConfiguration config)
        {
            config.MapODataServiceRoute("odata", null, GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
            config.EnsureInitialized();
        }

        private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.Namespace = "Demos";
            builder.ContainerName = "DefaultContainer";

            builder.EntitySet<Person>("People");

            var edmModel = builder.GetEdmModel();

            return edmModel;
        }
    }

然后请求可以正常运行http://localhost:21830/People?$filter=contains(Description,'Lorem')

答案 1 :(得分:0)

我终于发现了什么可能是错的,但我不知道如何解决它。

如果我正在尝试传递类似的参数查询:

http://(...)/People?$filter=SomeProperty eq 'Foo'

将OData查询选项应用于我的查询后,在我的WebAPI控制器方法中,即:

IQueryable<People> queryResults = (IQueryable<People>)queryOptions.ApplyTo(query);

在queryResults中有一个类似的片段:

WHERE (`Project1`.`SomeProperty` = @p__linq__0) 

一切正常。但当我通过这样的查询时:

http://(...)/People?$filter=contains(SomeProperty, 'Foo')

在queryResults中我可以看到:

WHERE (`Project1`.`SomeProperty` LIKE '%p__linq__0%')

总是没有结果。 我不知道我是否理解正确,但似乎它正在寻找包含文本'p__linq__0'的SomeProperty值,而不是寻找包含p__linq__0的的值(这是'Foo' )。


感谢您的回复,@ QianLi。 我的控制器看起来像那样:

public class PeopleController : ApiController
{
    readonly PeopleContext _context = new PeopleContext();

    public PageResult<People> Get(ODataQueryOptions<People> queryOptions)
    {
        var query = _context.People.OrderBy(x => x.SomeProperty1);
        var queryResults = (IQueryable<People>)queryOptions.ApplyTo(query);
        long cnt = 0;
        if (queryOptions.Count != null)
            cnt = long.Parse(Request.Properties["System.Web.OData.TotalCount"].ToString());

        return new PageResult<People>(queryResults, null, cnt);
    }
}

(这里解释了'cnt'的奇怪解决方法:Items count in OData v4 WebAPI response) 但现在我放弃使用Count,我将控制器实现更改为您所描述的内容:

[EnableQuery]
public class PeopleController : ODataController
{
    public IHttpActionResult Get()
    {
        var query = _context.People.OrderBy(x => x.SomeProperty1);
        return Ok(query);
    }
}

它的工作原理与之前相同 - 使用 eq 过滤查询, lt 等工作正常,包含根本不起作用

编辑:我知道!问题可能是使用此修复程序的结果:http://www.nuget.org/packages/Patches.System.Web.OData/5.3.0-datetimefixes而不是官方OData库。但我非常需要这个datetimefixes ...