145 votes

Comment transmettre plusieurs paramètres à un GET ASP.Net Web API ?

J'utilise l'API Web MVC4 de .Net pour mettre en œuvre (si tout va bien) une API RESTful. J'ai besoin de passer quelques paramètres au système et de lui faire exécuter une action, puis de retourner une liste d'objets comme résultats. Plus précisément, je dois transmettre deux dates et renvoyer les enregistrements qui se situent entre les deux. Je garde également une trace des enregistrements renvoyés afin que les appels ultérieurs ne soient pas retraités dans le système.

J'ai envisagé plusieurs approches :

  1. Sérialiser les paramètres en une seule chaîne JSON et la décortiquer dans l'API. http://forums.asp.net/t/1807316.aspx/1

  2. Passez les paramètres dans la chaîne de requête.
    Quelle est la meilleure façon de passer plusieurs paramètres de requête à une api restful ?

  3. Définir les paramètres dans la route : api/controller/date1/date2

  4. J'utilise un POST qui me permet de passer un objet avec des paramètres.

  5. Recherche d'ODATA puisque l'API Web le prend (actuellement) en charge. Je n'ai pas encore fait grand-chose avec ça, donc je ne suis pas très familier avec ça.

Il semble que les bonnes pratiques REST indiquent que lorsque des données sont extraites, il faut utiliser un GET. Cependant, GET doit également être nullipotent (ne produit pas d'effets secondaires), et je me demande si mon implémentation spécifique ne viole pas cela puisque je marque les enregistrements dans le système API, et donc que je produis des effets secondaires.

Cela m'a également conduit à la question de la prise en charge des paramètres variables. Si la liste des paramètres d'entrée change, il serait fastidieux de devoir redéfinir votre itinéraire pour le choix 3 si cela se produit souvent. Et que se passerait-il si les paramètres étaient définis au moment de l'exécution...

Dans tous les cas, pour ma mise en œuvre spécifique, quel choix (le cas échéant) semble le meilleur ?

153voto

mcpDESIGNS Points 8521

Je pense que le moyen le plus simple est d'utiliser simplement AttributeRouting .

C'est évident dans votre contrôleur, pourquoi voulez-vous que ce soit dans votre Global ? WebApiConfig fichier ?

Exemple :

    [Route("api/YOURCONTROLLER/{paramOne}/{paramTwo}")]
    public string Get(int paramOne, int paramTwo)
    {
        return "The [Route] with multiple params worked";
    }

El {} Les noms doivent correspondre à vos paramètres.

Aussi simple que cela, maintenant vous avez un GET qui gère les paramètres multiples dans cette instance.

12 votes

C'est génial. La plupart des gens recommandent de configurer l'itinéraire dans le WebApiConfig mais ceci est en effet plus agréable.

4 votes

En effet, nous (la plupart des gens) recommandons de disposer d'une zone de gestion centralisée pour votre configuration. Dans le cas des API Web (Microsoft ou autres), les modèles centralisés pour REST sont essentiels. Le routage des attributs est mignon, mais il rend les exceptions ponctuelles beaucoup trop tentantes.

3 votes

Je suis d'accord, je dois mettre à jour ma réponse en fait. Il y a une bien meilleure façon de faire des paramètres multiples avec les GETs. J'ai posté cette réponse lorsque j'étais plus novice en matière de WebAPI. Maintenant, je n'utilise plus l'AttributeRouting (sauf si je ne veux pas créer un nouveau contrôleur), et je passe tous les paramètres dans la QueryString, ils sont automatiquement mis en correspondance. Je mets à jour dès que j'en ai l'occasion pour que les gens n'utilisent pas cette ancienne méthode.

51voto

Graham Wright Points 114

Il suffit d'ajouter une nouvelle route à la WebApiConfig entrées.

Par exemple, pour appeler :

public IEnumerable<SampleObject> Get(int pageNumber, int pageSize) { ..

ajouter :

config.Routes.MapHttpRoute(
    name: "GetPagedData",
    routeTemplate: "api/{controller}/{pageNumber}/{pageSize}"
);

Ajoutez ensuite les paramètres à l'appel HTTP :

GET //<service address>/Api/Data/2/10

13 votes

Il semble que ce soit la seule réponse qui énumère toutes les pièces. J'aurais aimé que quelqu'un décrive mieux la façon d'utiliser les api/controller?start=date1&end=date2 URI de style.

0 votes

@Hot Licks La réponse d'Andrew Veriga fonctionne bien avec les arguments de type chaîne de requête. Essentiellement, vous liez les noms des chaînes de requête aux propriétés de la classe et les passez dans votre méthode. Votre méthode prendra un seul argument de classe marqué par l'attribut [FromUri] et aura vos arguments de chaîne de requête comme propriétés.

0 votes

C'est génial. Merci.

45voto

Nigel Findlater Points 638

Je viens de mettre en œuvre une api RESTfull où j'ai besoin de passer des paramètres. J'ai fait cela en passant les paramètres dans la chaîne de requête dans le même style que celui décrit dans le premier exemple de Mark "api/controller?start=date1&end=date2".

Dans le contrôleur, j'ai utilisé une astuce de Division d'URL en C# ?

// uri: /api/courses
public IEnumerable<Course> Get()
{
    NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
    var system = nvc["System"];
    // BL comes here
    return _courses;
}

Dans mon cas, j'appelais le WebApi via Ajax, comme suit :

$.ajax({
        url: '/api/DbMetaData',
        type: 'GET',
        data: { system : 'My System',
                searchString: '123' },
        dataType: 'json',
        success: function (data) {
                  $.each(data, function (index, v) {
                  alert(index + ': ' + v.name);
                  });
         },
         statusCode: {
                  404: function () {
                       alert('Failed');
                       }
        }
   });

J'espère que cela vous aidera...

2 votes

Je suppose que vous n'utilisez pas WebApi parce que ParameterBinding fera correspondre votre chaîne de requête aux paramètres de votre méthode api automatiquement...

1 votes

Oui, une meilleure solution serait d'utiliser un attribut comme [Route("api/DbMetaData/{system}/{searchString}")] et d'ajouter ces paramètres à la fonction Get(string system, string searchString), puis d'appeler avec "...api/DbMetaData/mysystem/mysearchstring".

0 votes

J'ai utilisé son exemple dans mon WebApi C# MVC et cela a bien fonctionné. +1 pour l'exemple

40voto

user1163269 Points 176

J'ai trouvé une excellente solution sur http://habrahabr.ru/post/164945/

public class ResourceQuery
{
   public string Param1 { get; set; }
   public int OptionalParam2 { get; set; }
}

public class SampleResourceController : ApiController
{
    public SampleResourceModel Get([FromUri] ResourceQuery query)
    {
        // action
    }
}

5 votes

L'indice ici est le [FromUri].

2 votes

Bien que l'article soit en russe, @tranceporter a raison. Le "FromUri" semble être un excellent moyen de récupérer les paramètres de l'url. Un autre article qui pourrait être utile : asp.net/web-api/overview/formats-et-modèle-liaison/

0 votes

C'est ce que je fais depuis un certain temps maintenant et ça marche très bien ! Je recommande également cette solution.

9voto

Mark Points 12663

Utilisation de GET o POST est clairement expliqué par @LukLed . En ce qui concerne la façon dont vous pouvez passer les paramètres, je suggérerais d'opter pour la deuxième approche (je ne m'y connais pas bien). ODATA soit).

1. sérialiser les paramètres en une seule chaîne JSON et la décortiquer dans l'API. http://forums.asp.net/t/1807316.aspx/1

Ce n'est pas facile à utiliser y Compatible avec les moteurs de recherche

2. passer les paramètres dans la chaîne de requête. Quelle est la meilleure façon de passer plusieurs paramètres de requête à une api restful ?

C'est l'approche habituellement préférable.

3. définition des paramètres dans la route : api/controller/date1/date2

Ce n'est certainement pas une bonne approche. Cela donne l'impression que quelqu'un date2 est une sous-ressource de date1 et ce n'est pas le cas. Les deux date1 y date2 sont des paramètres de requête et se situent au même niveau.

Dans le cas simple, je suggérerais un URI comme celui-ci,

api/controller?start=date1&end=date2

Personnellement, j'aime le modèle URI ci-dessous, mais dans ce cas, nous devons écrire du code personnalisé pour mapper les paramètres.

api/controller/date1,date2

0 votes

En fait, ce sont mes explications originales. Je pense que LukLed a fait briller mes tags et mon lien URL.

0 votes

En ce qui concerne le référencement, dans ce cas, il ne s'appliquerait pas. Ce code sera "serveur à serveur", donc je ne me soucierais pas que le monde extérieur le découvre un jour. En fait, je dois m'assurer que des mesures de sécurité appropriées sont prises pour éviter les accès aléatoires. J'ai dû faire la sérialisation JSON pour une autre partie du système (il semble qu'il y ait eu un bug en essayant de POSTer de grandes listes d'objets et j'ai dû les sérialiser en chaîne), donc ce ne serait pas un gros problème dans ce cas.

1 votes

J'espère que vous avez déjà des réponses alors pourquoi vous posez cette question ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X