web-dev-qa-db-fra.com

Comment dois-je transmettre plusieurs paramètres à une API Web ASP.Net GET?

J'utilise l'API Web .Net MVC4 pour (j'espère) implémenter une API RESTful. J'ai besoin de transmettre quelques paramètres au système et de le faire exécuter, puis de renvoyer une liste d'objets comme résultats. Plus précisément, je passe deux dates et je retourne des disques qui se situent entre elles. Je garde également une trace des enregistrements renvoyés afin que les appels suivants ne soient pas retraités dans le système.

J'ai envisagé quelques approches:

  1. Sérialisation des paramètres dans une seule chaîne JSON et sélection dans l'API . http://forums.asp.net/t/1807316.aspx/1

  2. Passez les paramètres dans la chaîne de requête.
    Quel est le meilleur moyen de passer plusieurs paramètres de requête à une API reposante?

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

  4. Utiliser un POST qui me permet intrinsèquement de transmettre un objet avec params.

  5. Recherche d'ODATA depuis que l'API Web (actuellement) le prend en charge. Je n'ai pas encore beaucoup travaillé avec ça, donc je ne le connais pas très bien.

Il semble que les pratiques appropriées REST indiquent que lorsque des données sont extraites, vous devez utiliser un GET. Cependant, GET devrait également être nullipotent (ne produit aucun effet secondaire), et je me demande si mon implémentation spécifique ne le respecte pas puisque je marque des enregistrements dans le système API, d’où des effets secondaires.

Cela m'a également amené à 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 pourrait-il se passer si les paramètres sont définis au moment de l'exécution ...

En tout cas, pour ma mise en œuvre spécifique, quel choix (le cas échéant) semble le mieux?

119
sig606

Que signifie ce marquage d'enregistrement? Si cela est utilisé uniquement à des fins de journalisation, j'utiliserais GET et désactiverais toute la mise en cache, car vous souhaitez consigner chaque requête pour ces ressources. Si le marquage d'enregistrement a un autre objectif, POST est la voie à suivre. L'utilisateur doit savoir que ses actions affectent le système et que la méthode POST est un avertissement.

10
LukLed

Je pense que le moyen le plus simple consiste simplement à utiliser AttributeRouting.

C'est évident dans votre contrôleur, pourquoi voudriez-vous cela dans votre fichier Global WebApiConfig?

Exemple:

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

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

Aussi simple que cela, vous avez maintenant une GET distincte qui gère plusieurs paramètres dans cette instance.

Ajoutez simplement un nouvel itinéraire aux entrées WebApiConfig.

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 
48
Graham Wright

Je viens juste de mettre en place une API RESTfull où je dois transmettre des paramètres. Je l'ai fait en passant les paramètres de 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 URL divisée 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 WebApi via Ajax et ressemblait à ceci:

$.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 ça aide...

44
Nigel Findlater

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
    }
}
37
Andrew Veriga

L'utilisation de GET ou POST est clairement expliquée par @LukLed. En ce qui concerne les moyens de passer les paramètres, je suggérerais d’utiliser la deuxième approche (je ne connais pas grand chose de ODATA non plus).

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

Ce n'est pas convivial et SEO convivial

2.Passez les paramètres dans la chaîne de requête. Quel est le meilleur moyen de passer plusieurs paramètres de requête à une API reposante?

C'est l'approche généralement préférable.

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

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

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

api/controller?start=date1&end=date2

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

api/controller/date1,date2
8
VJAI
8
danan
 [Route("api/controller/{one}/{two}")]
    public string Get(int One, int Two)
    {
        return "both params of the root link({one},{two}) and Get function parameters (one, two)  should be same ";
    }

Les paramètres du lien racine ({un}, {deux}) et des paramètres de la fonction Get (un, deux) doivent être identiques.

2
ashwath hegde
    public HttpResponseMessage Get(int id,string numb)
    {
        //this will differ according to your entity name
        using (MarketEntities entities = new MarketEntities())
        {
          var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
            if (ent != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, ent);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
            }
        }
    }
0
Jesse Mwangi

Avec .Net core peut faire comme suit.

    [Route("api/[controller]")]
    [ApiController]
    public class ReportController : ControllerBase
    {
...
...        
        // GET api/report/5454510/10/abc
        [HttpGet("{id}/{page}/{etc}")]
        public async Task<ActionResult<string>> Get(string id, int page, string etc)
0
DineshNS

Je sais que c'est vraiment vieux, mais je voulais la même chose récemment et voici ce que j'ai trouvé ...

    public HttpResponseMessage Get([FromUri] string var, [FromUri] string test) {
        var retStr = new HttpResponseMessage(HttpStatusCode.OK);
        if (var.ToLower() == "getnew" && test.ToLower() == "test") {
            retStr.Content = new StringContent("Found Test", System.Text.Encoding.UTF8, "text/plain");
        } else {
            retStr.Content = new StringContent("Couldn't Find that test", System.Text.Encoding.UTF8, "text/plain");
        }

        return retStr;
    }

Alors maintenant, dans votre adresse/URI/...

http (s): // myURL/api/myController /? var = getnew & test = test

Résultat: "Test trouvé"


http (s): // myURL/api/myController /? var = getnew & test = rien

Résultat: "Impossible de trouver ce test"

0
Rick Riggs