2017-07-03 1 views
4

J'ai un projet Web API qui est utilisé depuis plusieurs années sans le support d'OData, avec des paramètres d'URL standard. Je souhaite maintenant ajouter le support OData à cette API, mais comme l'API n'est pas construite sur un modèle interrogeable, l'intention est de recevoir l'objet ODataQueryOptions<T> et de le transmettre à un dépôt. Tout ce que je peux trouver à propos de la prise en charge d'OData suppose que j'ai un modèle interrogeable ou est trop simpliste et me dit simplement comment donner un sens à l'objet ODataQueryOptions. Par conséquent, je suis incapable de mettre en place une méthode simple.Prise en charge d'ODataQueryOptions dans l'API Web existante

Voici ce que j'ai actuellement.

[Route("test")] 
[HttpGet] 
[EnableQuery] 
public IHttpActionResult Test(ODataQueryOptions<TestOptions> options) 
{ 
    var settings = new ODataValidationSettings { 
      AllowedFunctions = AllowedFunctions.None, 
      AllowedLogicalOperators = AllowedLogicalOperators.Equal, 
      AllowedArithmeticOperators = AllowedArithmeticOperators.None, 
      AllowedQueryOptions = AllowedQueryOptions.Filter 
     }; 
    try 
    { 
     options.Validate(settings); 
    } 
    catch (ODataException exception) 
    { 
     return BadRequest(exception.Message); 
    } 

    var binaryOperator = options.Filter?.FilterClause?.Expression as BinaryOperatorNode; 
    if (binaryOperator != null) 
    { 
     var property = binaryOperator.Left as SingleValuePropertyAccessNode ?? binaryOperator.Right as SingleValuePropertyAccessNode; 
     var constant = binaryOperator.Left as ConstantNode ?? binaryOperator.Right as ConstantNode; 

     if (property?.Property != null && constant?.Value != null) 
     { 
      ; 
     } 
    } 

    return Ok(); 
} 

La TestOptions classe (dans le ODataQueryOptions<TestOptions> param) est actuellement une classe vide:

public class TestOptions 
{ 
} 

J'ai aussi ajouté

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // existing code 

     config.AddODataQueryFilter(); 
    } 
} 

Cependant, lors de l'appel de cette d'une API REST client ...

{
"Message": "Une erreur s'est produite",
"ExceptionMessage": "Aucune route HTTP non-OData enregistrée. »,
"ExceptionType": "System.InvalidOperationException",
"StackTrace": "..."
}

Qu'ai-je manqué je l'aurais pensé que je pourrais avoir à vous inscrire? OData-enabled méthodes dans le global.asax ou similaire, mais l'exception implique que le problème est avec des méthodes non-OData, mais toutes les autres méthodes retournent toujours comme prévu (soit, sans aucune participation OData)

+0

Je pense que le message d'erreur est quelque peu trompeur ici et que vous devez enregistrer l'itinéraire OData. Suivez les instructions ici pour commencer: https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an -odata-v4-endpoint – TomDoesCode

+0

Cet exemple est construit sur un modèle EF et comme je l'ai dit dans le PO, je n'ai pas de modèle sous-jacent. L'exemple enregistre le point de terminaison OData avec des détails spécifiques de son modèle: https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint # configure-the-odata-endpoint – awj

+0

OK, vous avez quand même besoin de construire un modèle, même si ce n'est pas à travers le framework d'entité. Votre modèle sera-t-il défini au moment de la compilation? I.E les types et propriétés exposés seront-ils modifiés? – TomDoesCode

Répondre

3

En fait, cela fonctionne parfaitement sans EntityDate ou toute autre configuration de modèle. Vous avez juste besoin d'un List<Poco.Language> que vous pouvez convertir avec .AsQueryable() et c'est parti.

[Route(""), HttpGet] 
public IHttpActionResult Get(ODataQueryOptions<Poco.Language> queryOptions) 
{   
    return Ok(queryOptions.ApplyTo(_repository.GetAll().AsQueryable())); 
} 

Au-dessus de contrôleur peut être appelé avec tous les types d'options de requête OData, routes normales et aucune installation dans le WebApiConfig.

Poco.Language est juste une classe C# POCO simple.

+1

Exactement ce que je cherchais! – awj

+0

Dans le cas où vous avez toujours le problème, en fonction de la version de la bibliothèque OData, ajoutez également 'config.EnableDependencyInjection();' dans vos configurations webapi. Voir https://github.com/OData/WebApi/issues/816 – Chandermani

0

L'avez-vous ajouté à votre Startup?J'essaie de faire la même chose que vous, mais avec un .Net Core Web Api. J'ai téléchargé les échantillons de https://github.com/OData/ODataSamples et il a un projet de travail qui fait exactement ce que nous essayons de faire. Regardez ODataQueryableSample.csproj. Il n'utilise pas EntityFramework, crée simplement une liste en mémoire.

En outre, je ne pense pas que vous ayez besoin à la fois de l'attribut [EnableQuery] et du paramètre ODataQueryOptions - l'exemple donne un exemple pour les deux et ne les utilise pas ensemble. Je n'ai pas réussi à travailler avec mon projet, mais je l'ai vu fonctionner sur mon PC, donc je crois que c'est juste une chose de configuration (par exemple, mon démarrage utilise IApplicationBuilder au lieu de IAppBuilder). Vous pouvez également essayer de le faire à partir d'un navigateur pour obtenir un meilleur message d'exception.