134 votes

Méthode HttpPost multiple dans le contrôleur de l’API Web

Je commence à utiliser MVC4 projet d'API Web, j'ai contrôleur avec plusieurs HttpPost méthodes. Le Contrôleur se présente comme suit:

Contrôleur

public class VTRoutingController : ApiController
{
    [HttpPost]
    public MyResult Route(MyRequestTemplate routingRequestTemplate)
    {
        return null;
    }

    [HttpPost]
    public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate)
    {
        return null;
    }
}

Ici, MyRequestTemplate représente le modèle de la classe responsable de la gestion du Json à venir grâce à la demande.

Erreur:

Quand je fais une demande à l'aide de Fiddler pour http://localhost:52370/api/VTRouting/TSPRoute ou http://localhost:52370/api/VTRouting/Route j'obtiens une erreur:

Plusieurs actions ont été trouvés qui correspondent à la demande

Si je supprime l'un de la méthode ci-dessus, il fonctionne très bien.

Mondiale.asax

J'ai essayé de modifier la valeur par défaut de la table de routage en global.asax, mais je reçois toujours le message d'erreur, je pense que j'ai un problème dans la définition des itinéraires mondiale.asax. Voici ce que je fais mondiale.asax.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapHttpRoute(
            name: "MyTSPRoute",
            routeTemplate: "api/VTRouting/TSPRoute",
            defaults: new { }
      );

    routes.MapHttpRoute(
        name: "MyRoute",
        routeTemplate: "api/VTRouting/Route",
        defaults: new {action="Route" }
    );
}

Je suis en faisant la demande dans un violon à l'aide de POST, en passant json dans RequestBody pour MyRequestTemplate.

150voto

Asif Mushtaq Points 7943

Vous pouvez avoir des actions multiples dans un seul contrôleur.

Pour cela, vous devez faire les deux choses suivantes.

  • Tout d’abord décorer avec des actions d’attribut comme
  • Définir ensuite les lignes suivantes dans `` fichier.

28voto

Filip W Points 13343

utilisation:

routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

ce n'est pas une bonne approche, mais vous pouvez maintenant appeler vos actions par un nom plutôt que de laisser l'API Web de déterminer automatiquement pour vous basé sur le verbe) comme ceci:

[POST] /api/VTRouting/TSPRoute

[POST] /api/VTRouting/Route

Contrairement à la croyance populaire, il n'y a rien de mal avec cette approche, et ce n'est pas abuser de l'API Web. Vous pouvez toujours tirer parti de toutes les caractéristiques impressionnantes de l'API Web (avec délégation des gestionnaires, la négociation de contenu, mediatypeformatters et ainsi de suite) - vous venez de laisser tomber l'approche RESTful.

13voto

Andrew Backer Points 3009

Une api web d'extrémité (controller) est une ressource unique qui accepte get/post/put/delete verbes. C'est pas normal MVC contrôleur.

Forcément, en /api/VTRouting il ne peut être un HttpPost méthode qui accepte les paramètres que vous envoyez. Le nom de la fonction n'a pas d'importance, aussi longtemps que vous décorez avec les [http] trucs. Je n'ai jamais essayé, mais.

Edit: Cela ne fonctionne pas. Dans la résolution, il semble aller par le nombre de paramètres, pas de modèle-lier le type.

Vous pouvez surcharger les fonctions d'accepter des paramètres différents. Je suis assez sûr que vous seriez OK si vous avez déclaré la façon dont vous faites, mais utilisé différents (incompatible) les paramètres pour les méthodes. Si les paramètres sont les mêmes, vous êtes hors de la chance que le modèle de liaison de ne pas connaître celui que vous avez voulu dire.

[HttpPost]
public MyResult Route(MyRequestTemplate routingRequestTemplate) {...}

[HttpPost]
public MyResult TSPRoute(MyOtherTemplate routingRequestTemplate) {...}

Cette partie fonctionne

Le modèle par défaut ils donnent lorsque vous créez un nouveau c'est assez explicite, et je dirais que vous devriez coller avec de la présente convention:

public class ValuesController : ApiController
{
    // GET is overloaded here.  one method takes a param, the other not.
    // GET api/values  
    public IEnumerable<string> Get() { .. return new string[] ... }
    // GET api/values/5
    public string Get(int id) { return "hi there"; }

    // POST api/values (OVERLOADED)
    public void Post(string value) { ... }
    public void Post(string value, string anotherValue) { ... }
    // PUT api/values/5
    public void Put(int id, string value) {}
    // DELETE api/values/5
    public void Delete(int id) {}
}

Si vous voulez faire une classe qui fait beaucoup de choses, pour l'ajax, il n'y a pas de grande raison de ne pas utiliser un contrôleur standard/modèle d'action. La seule vraie différence, c'est votre méthode de signatures ne sont pas aussi jolie, et vous avez pour envelopper les choses en Json( returnValue) avant de vous les retourner.

Edit:

La surcharge fonctionne très bien lors de l'utilisation du modèle standard (modifié pour inclure) lors de l'utilisation de types simples. J'ai fait et testé dans l'autre sens aussi, avec 2 objets personnalisés avec des signatures différentes. N'a jamais pu le faire fonctionner.

  • Liaison avec des objets complexes ne regarde pas "profond", donc c'est un no-go
  • Vous pourriez contourner ce problème en passant un supplément de param, sur la chaîne de requête
  • Une meilleure description que je peux donner sur les options disponibles

Cela a fonctionné pour moi dans ce cas, de voir où il reçoit de vous. Exception à des fins de test.

public class NerdyController : ApiController
{
    public void Post(string type, Obj o) { 
        throw new Exception("Type=" + type + ", o.Name=" + o.Name ); 
    }
}

public class Obj {
    public string Name { get; set; }
    public string Age { get; set; }
}

Et appelé comme cette forme de la console:

$.post("/api/Nerdy?type=white", { 'Name':'Slim', 'Age':'21' } )

-1voto

mobygeek Points 110
public class Journal : ApiController
{
    public MyResult Get(journal id)
    {
        return null;
    }
}

public class Journal : ApiController
{

    public MyResult Get(journal id, publication id)
    {
        return null;
    }
}

Je ne suis pas sûr de savoir si la surcharge get/post la méthode est contraire à la notion de détente de l'api,mais il workds. Si quelqu'un pouvait éclairer sur cette question. Que faire si j'ai un uri comme

uri:/api/journal/journalid
uri:/api/journal/journalid/publicationid

donc, comme vous pouvez le voir mon journal de tri de aggregateroot, si je peux définir un autre contrôleur pour la publication uniquement et de transmettre le numéro d'id de la publication dans mon url toutefois cela donne beaucoup plus de sens. depuis ma publication n'existerait pas sans la revue elle-même.

-1voto

Rony Tesler Points 53

Je viens d’ajouter « action = action_name » à l’url et de cette façon, le moteur de routage sait quelle action je veux. J’ai aussi ajouté l’attribut ActionName aux actions, mais je ne suis pas sûr que cela est nécessaire.

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