OData错误:URI中指定的查询无效。 该属性不能在查询选项中使用

我正试图让OData端点启动并正常工作,我遇到了这个错误,即使谷歌也没什么可说的。

我已经创建了一个Entity Framework EDMX上下文(数据库优先),让设计者从中生成2个模型。

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

我可以做得很好:

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

它检索主ID为6587660的项目。

但是任何$filter请求都是这样的:

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

将失败并出现以下错误:

URI中指定的查询无效。 属性“ProjectID”不能在$ filter查询选项中使用。

我也尝试过查询其他属性,字符串属性。 同样的错误。

我已经检查过EF生成的模型在属性上没有任何属性,但它们没有。

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

 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("Projects"); config.MapODataServiceRoute( routeName: "ODataRoute", routePrefix: null, model: builder.GetEdmModel() ); } 

这是Projects控制器(GetProjects是进行$ filter查询时的被调用方法):

 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 GetProjects() { return db.Projects; } // GET: odata/Projects(5) [EnableQuery] public SingleResult 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 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 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和Database First,所以我不确定是什么导致了这一点。

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

来自文档13.1模型绑定属性 :

现在,WebAPI OData的默认设置是:客户端无法在查询中应用$ count,$ orderby,$ select,$ top,$ expand,$ filter,查询如localhost \ odata \ Customers?$ orderby = Name将失败为BadRequest,因为默认情况下所有属性都不可排序,这是6.0.0中的重大更改

因此,我们现在需要启用OData模型绑定属性,您可以使用以下块中的中间行进行全局操作(另外两个是您的代码):

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

但这是一个包罗万象的工作,围绕着这种变化带来的更好的安全性/性能。

因此,您可以并且可能应该使用每个实体的流畅API调用启用OD​​ata模型绑定属性,如下所示:

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

这个答案应该可以解决您发布的问题但我希望您需要查看这些文档 ,以便为项目的其余部分提供全面的解决方案(当然,除非您只是部署一个-line catch all!)。


正如名称“模型绑定属性”所暗示的那样,您还可以通过模型上的属性来实现所需的内容,这也是文档中的(实际上也是主要关注点)。


2017年2月编辑:

每个实体的流畅API中似乎存在一个错误。 尽管使用流畅的API设置了实体集,但是对$expand实体集的调用会间歇性地返回400 Bad Request并在原始问题中出现错误。 我不知道这个bug是否只存在于$expand或其他查询参数上。 我也不知道是我的代码是导致问题还是MS错误,因此是其他人遇到的问题。 我将很快对此进行调查并更新此答案。 现在我正在使用单线捕捉全部; 工作得很好。

进一步编辑:

我刚刚重读了一些文档 (尽量让这个更新变得可以理解),它们似乎暗示我现在设置的方式(使用Global Config one-line-catch-all加上流畅的API) ,每个实体的流畅API仍将受到尊重,因为:

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

因此,也许这就是你要做的事情:添加one-line-catch-all然后使用模型绑定属性,流畅API或两者进行微调。 我需要对此进行测试并尽快报告…