J'essaie de mettre en place un point d'accès OData et de le faire fonctionner, mais je rencontre une erreur que même Google n'arrive pas à expliquer.
J'ai créé un contexte Entity Framework EDMX (base de données en premier), j'ai demandé au concepteur de générer 2 modèles à partir de celui-ci.
Tout fonctionne bien, sauf $filter
les requêtes échouent.
Je peux très bien le faire :
http://localhost:27164/Projects(6587660)
Ce qui permet de retrouver le projet dont l'ID primaire est 6587660.
Mais tout $filter
les demandes en tant que telles :
http://localhost:27164/Projects?$filter=ProjectID eq 6587660
échouera avec l'erreur suivante :
La requête spécifiée dans l'URI n'est pas valide. La propriété 'ProjectID' ne peut pas être utilisée dans l'option de requête $filter.
J'ai également essayé d'interroger d'autres propriétés, notamment des propriétés de type chaîne. Même erreur.
J'ai vérifié que le modèle généré par EF n'a pas d'attributs sur les propriétés, ils n'en ont pas.
Voici ma méthode Register dans le module WebApiConfig.cs :
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()
);
}
Voici le contrôleur Projects (GetProjects est la méthode appelée lors d'une requête $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<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;
}
}
C'est la première fois que j'utilise OData avec Database First, je ne suis donc pas sûr de la cause de ce problème.
J'utilise les derniers runtimes de Nuget sur .NET 4.5.2.
0 votes
Serait-ce le cas de la propriété ? Avez-vous essayé
$filter=projectId eq 6587660
o$filter=projectID eq 6587660
?0 votes
@Igor J'ai essayé. Tout autre cas renvoie une erreur disant que la propriété n'existe pas, donc j'ai eu le bon casing.
0 votes
Avez-vous essayé
$filter
avec une autre propriété du modèle, comme une propriété de type chaîne de caractères ?0 votes
Avez-vous des ces options activé (ou non défini) qu'il vous empêcherait d'utiliser
$filter
? Pour l'instant, il s'agit de beaucoup de suppositions et de questions, vous devriez fournir du code comme la configuration ET le contrôleur odata que vous utilisez pour donner plus d'informations.0 votes
J'ai exactement le même problème. En fait, je ne peux utiliser aucun des paramètres de syntaxe de requête, $count, $filter, $select, etc. Ils échouent tous.
0 votes
Public class CustomersController : ODataController { ProductsContext db = new ProductsContext() ; [EnableQuery(AllowedQueryOptions = System.Web.OData.Query.AllowedQueryOptions.All)] public IQueryable<Customer> Get() { var got = db.Customers.Include( c => c.Orders ) ; return got.AsQueryable() ; } }. }
0 votes
@Igor si le nom de la propriété était erroné, comme vous vous le demandez dans votre premier commentaire, le message d'erreur signalerait que : la formulation de ce message d'erreur est telle que nous savons que la propriété peut être trouvée, elle ne peut simplement pas être utilisée dans un filtre. Voir ma réponse pour savoir comment permettre à cette propriété d'être filtrée. Les options que vous indiquez dans votre autre commentaire sont pour une ancienne version d'OData et n'aideront pas à résoudre ce problème AFAIK. HTH.
0 votes
@RaviDesai Jetez un coup d'œil à ma réponse ; j'espère qu'elle résoudra aussi votre problème, ce qui devrait être le cas puisque c'est exactement la même chose ;-).