Asp.net web api OData v4中的系统查询选项$filter(规范函数)

Asp.net web api OData v4中的系统查询选项$filter(规范函数),asp.net-web-api,filter,odata,Asp.net Web Api,Filter,Odata,根据本文件: 我应该能够通过$filter参数查询传递,比如“$filter=contains(PropertyName,'SomeValue')” 当我传递逻辑运算符时(例如: $filter=PropertyName eq'SomeValue')它工作正常。但是像“contains”、“substring”、“endswith”、“startswith”等函数永远不起作用——将ODataQueryOptions应用到DbSet的查询结果总是一个空集 你知道为什么吗?那么你是说$filter=

根据本文件: 我应该能够通过$filter参数查询传递,比如“$filter=contains(PropertyName,'SomeValue')”

当我传递逻辑运算符时(例如: $filter=PropertyName eq'SomeValue')它工作正常。但是像“contains”、“substring”、“endswith”、“startswith”等函数永远不起作用——将ODataQueryOptions应用到DbSet的查询结果总是一个空集


你知道为什么吗?

那么你是说$filter=contains(PropertyName,'SomeValue')不适用于你的服务?该功能本身可以很好地工作,请尝试使用?$filter=contains(FirstName,'Angel')。如果您显示代码的更多细节,它将帮助其他人解决您的问题。您可以查看ODataV4示例服务的实现,或者了解Queryable和$filter的工作原理


因为你没有发布你的代码,我不确定是什么问题,我只是有一个快速的实现,$过滤器可以很好地工作。希望这能有所帮助

模范人物

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;
        }
    }
公共静态类WebApiConfig
{
公共静态无效寄存器(HttpConfiguration配置)
{
config.MapODataServiceRoute(“odata”,null,GetEdmModel(),新的DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
config.EnsureInitialized();
}
私有静态IEdmModel GetEdmModel()
{
ODataConventionModelBuilder=新ODataConventionModelBuilder();
builder.Namespace=“Demos”;
builder.ContainerName=“DefaultContainer”;
建筑商实体集(“人员”);
var edmModel=builder.GetEdmModel();
返回模型;
}
}

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

我终于发现了可能的错误,但我不知道如何修复它

如果我试图像这样传递参数查询:

http://(...)/People?$filter=SomeProperty eq 'Foo'
WHERE (`Project1`.`SomeProperty` = @p__linq__0) 
http://(...)/People?$filter=contains(SomeProperty, 'Foo')
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);
    }
}
将OData查询选项应用于我的查询后,在我的WebAPI控制器方法中,即:

IQueryable<People> queryResults = (IQueryable<People>)queryOptions.ApplyTo(query);
一切正常。但当我通过这样的查询时:

http://(...)/People?$filter=SomeProperty eq 'Foo'
WHERE (`Project1`.`SomeProperty` = @p__linq__0) 
http://(...)/People?$filter=contains(SomeProperty, 'Foo')
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);
    }
}
在queryResults中,我可以看到:

WHERE (`Project1`.`SomeProperty` LIKE '%p__linq__0%')
而且总是没有结果。 我不知道我是否理解正确,但它似乎是在寻找一些包含文本“p__linq__0”的属性值,而不是寻找包含p__linq__0(即“Foo”)的值的值


谢谢你的回复,千里。 我的控制器是这样的:

http://(...)/People?$filter=SomeProperty eq 'Foo'
WHERE (`Project1`.`SomeProperty` = @p__linq__0) 
http://(...)/People?$filter=contains(SomeProperty, 'Foo')
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);
    }
}
它的工作原理与之前相同-使用eq、lt等过滤查询。工作正常,contains根本不工作


编辑:我知道!问题可能是使用此修复程序而不是官方OData库的结果。但是我非常需要这个datetimefixes…

你能将
GET
请求的控制器方法附加到你想要过滤的实体集吗?因为你没有发布你的代码,我不确定是什么问题,我只是在我发布的答案中有一个快速实现,$filter可以很好地工作。希望能有帮助。谢谢。不幸的是,它仍然不起作用。我发布了我的控制器代码。控制器应该继承自
ODataController
,而不是
ApiController
。是的,它现在继承自ODataController,正如我在上面的帖子中所看到的。它仍然不能正常工作……您是否在返回代码中添加了
AsQueryable()
?这就是
var query=\u context.People.OrderBy(x=>x.SomeProperty1.AsQueryable()