OData错误:URI中指定的查询无效。该属性不能在查询选项中使用 [英] OData Error: The query specified in the URI is not valid. The property cannot be used in the query option

查看:466
本文介绍了OData错误:URI中指定的查询无效。该属性不能在查询选项中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获得一个OData端点并且正在工作,我有这个错误,即使Google没有太多的话要说。

I'm trying to get an OData endpoint up and working and I'm having this error that even Google doesn't have much to say about.

我已经创建了一个实体框架EDMX上下文(数据库首先),如果设计者从它生成2个模型。

I have created an Entity Framework EDMX context (database first), had the designer generate 2 models from it.

一切都正常,除了 $ filter 查询失败。

Everything is working fine, except $filter queries fail.

我可以做到这一点:

http://localhost:27164/Projects(6587660)

哪些检索项目主要ID为6587660。

Which retrieves the Project with a primary ID of 6587660.

但是,任何 $ filter 请求如下:

http://localhost:27164/Projects?$filter=ProjectID eq 6587660

将失败并出现以下错误:

Will fail with the following error:


URI中指定的查询无效。我们也尝试查询其他属性,字符串属性,也可以在$ filter query选项中使用属性ProjectID。

The query specified in the URI is not valid. The property 'ProjectID' cannot be used in the $filter query option.



< 。相同的错误。

I've also tried querying other properties, string properties too. Same error.

我已经检查了EF生成的模型在属性上没有任何属性,而不是。

I've checked that the model generated by EF doesn't have any attributes on the properties, they don't.

这是我在WebApiConfig.cs模块中的注册方法:

Here's my Register method in WebApiConfig.cs module:

using System.Web.OData.Builder;
using System.Web.OData.Extensions;

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    // Configure Web API to use only bearer token authentication.
    config.SuppressDefaultHostAuthentication();
    config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));


    ODataModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<DB.Project>("Projects");
    config.MapODataServiceRoute(
        routeName: "ODataRoute",
        routePrefix: null,
        model: builder.GetEdmModel()
    );           

}

这是项目控制器(GetProjects是执行时调用的方法一个$过滤器查询):

Here's the Projects controller (GetProjects is the called method when doing a $filter query):

public class ProjectsController : ODataController
{
    private AppContext db = new AppContext();

    //I've tried decorating with that: [EnableQuery(AllowedQueryOptions = System.Web.OData.Query.AllowedQueryOptions.All, AllowedArithmeticOperators = System.Web.OData.Query.AllowedArithmeticOperators.All)] and no go
    [EnableQuery]
    public IQueryable<Project> GetProjects()
    {
        return db.Projects;
    }

    // GET: odata/Projects(5)
    [EnableQuery]
    public SingleResult<Project> GetProject([FromODataUri] int key)
    {
        return SingleResult.Create(db.Projects.Where(project => project.ProjectID == key));
    }

    /*
    // PUT: odata/Projects(5)
    public IHttpActionResult Put([FromODataUri] int key, Delta<Project> patch)
    {
        Validate(patch.GetEntity());

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        Project project = db.Projects.Find(key);
        if (project == null)
        {
            return NotFound();
        }

        patch.Put(project);

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ProjectExists(key))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return Updated(project);
    }

    // POST: odata/Projects
    public IHttpActionResult Post(Project project)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.Projects.Add(project);
        db.SaveChanges();

        return Created(project);
    }

    // PATCH: odata/Projects(5)
    [AcceptVerbs("PATCH", "MERGE")]
    public IHttpActionResult Patch([FromODataUri] int key, Delta<Project> patch)
    {
        Validate(patch.GetEntity());

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        Project project = db.Projects.Find(key);
        if (project == null)
        {
            return NotFound();
        }

        patch.Patch(project);

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ProjectExists(key))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return Updated(project);
    }

    // DELETE: odata/Projects(5)
    public IHttpActionResult Delete([FromODataUri] int key)
    {
        Project project = db.Projects.Find(key);
        if (project == null)
        {
            return NotFound();
        }

        db.Projects.Remove(project);
        db.SaveChanges();

        return StatusCode(HttpStatusCode.NoContent);
    }
    */

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }

    private bool ProjectExists(int key)
    {
        return db.Projects.Count(e => e.ProjectID == key) > 0;
    }
}

这是我第一次使用OData数据库首先,所以我不知道是什么导致这个。

This is the first time I'm using OData with Database First so I'm not sure what's causing this.

我正在使用最新的运行时Nuget在.NET 4.5.2。

I'm using the latest runtimes from Nuget on .NET 4.5.2.

推荐答案

文档13.1模型绑定属性


现在WebAPI OData的默认设置是:客户端不能应用
$ count,$ orderby,$ select,$ top,$ expand,$ filter在查询中查询
像localhost\odata\Customers?$ orderby = Name将失败为
BadRequest,因为默认情况下所有属性都不可排序,所以
是6.0.0中的一个突破性变化。

Now the default setting for WebAPI OData is : client can’t apply $count, $orderby, $select, $top, $expand, $filter in the query, query like localhost\odata\Customers?$orderby=Name will failed as BadRequest, because all properties are not sort-able by default, this is a breaking change in 6.0.0

所以,我们现在需要启用OData模型绑定属性,您可以 可以 在下面的块中使用中间行(另外两个是你的c ode):

So, we now need to enable OData Model Bound Attributes which you can do globally with the middle line in the following block (the other two are your code):

ODataModelBuilder builder = new ODataConventionModelBuilder();
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null); //new line
builder.EntitySet<DB.Project>("Projects");

但是,这是一个全面而有益的工作,围绕更好的安全性/性能

所以,您可以(也许应该)使用流动的API调用来启用OData模型绑定属性,例如:

So, you can, and maybe should, enable OData Model Bound Attributes using fluent API calls per entity like this:

builder.EntitySet<DB.Project>("Projects"); //your line of code
builder.EntityType<DB.Project>().Filter("ProjectID");

这个答案应该解决你发布的问题,但是我希望你需要看看在这些文档,使您能够为您的项目的其余部分(除非您只是部署所有的一线全部!)。

This answer should solve the problem you posted about but, I expect, you will need to take a look at those docs to enable you to work up a comprehensive solution for the rest of your project (unless, of course, you just deploy the one-line catch all!).

名称模型绑定属性表明,您还可以通过模型上的属性来实现所需要的(实际上是主要的重点)文档

As the name "Model Bound Attribute" suggests, you can also achieve what you need via attributes on your models, which is covered in (in fact, is the main focus of) the docs too.

编辑2017年2月:

每个实体流畅的API似乎有一个错误。调用 $ expand 实体集间歇地返回400错误请求与原始问题的错误,尽管实体集是使用流畅的API设置。我不知道这个bug是否存在于 $ expand 或其他查询参数。我也不知道是否是我的代码是导致问题或MS错误,因此其他人正在遇到。我会尽快进行调查,并更新此答案。现在我正在使用一线捕捉全部;

There appears to be a bug in the per-entity fluent API. Calls to $expand entity-sets intermittently return a 400 Bad Request with the error in the original question despite the entity sets being set up with fluent API. I don't know whether this bug only exists on $expand or with other query params. I also don't know whether it is my code that is causing the problem or an MS bug and therefore something others are encountering. I will investigate this further soon and update this answer. For now I am using the one-line catch all; that works just fine.

进一步修改:

我刚刚重读了一些的文档(尝试将此更新尽可能可理解) ),他们似乎暗示我现在的方式(全球配置一线全部加上流利的API),每个实体流畅的API仍然会被尊重,因为:

I have just reread some of the docs (to try and get this update as understandable as possible) and they seem to imply that the way I now have things set up (with the Global Config one-line-catch-all plus fluent API), the per-entity fluent API will still be respected because:


查询设置可放置在许多地方,以下
优先级从最低到最高:系统默认值(不可查询
默认),全局配置,模型绑定属性,Fluent API。

"Query settings can be placed in many places, with the following precedence from lowest to highest: System Default(not query-able by default), Global Configuration, Model Bound Attribute, Fluent API."

因此,也许这是你必须做的:add单行捕获,然后微调模型绑定属性,流畅的API或两者。我需要测试一下,并会尽快回报...

Therefore, maybe this is what you have to do: add the one-line-catch-all and then fine-tune with model-bound-attributes, fluent API or both. I need to test this and will report back soon...

这篇关于OData错误:URI中指定的查询无效。该属性不能在查询选项中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆