web-dev-qa-db-fra.com

Plusieurs actions correspondant à la demande dans Web Api ont été trouvées

Je continue à avoir cette erreur lorsque j'essaie d'avoir 2 méthodes "Get"

Plusieurs actions correspondant à la demande ont été trouvées: webapi

J'ai regardé les autres questions similaires à ce sujet sur la pile mais je ne comprends pas.

J'ai 2 noms différents et j'utilise l'attribut "HttpGet"

[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}
212
chobo2

Votre feuille de route ressemble probablement à ceci:

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

Mais pour avoir plusieurs actions avec la même méthode http, vous devez fournir à webapi plus d’informations via l’itinéraire comme ceci:

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

Notez que la routeTemplate inclut maintenant une action. Beaucoup plus d'informations ici: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Mettre à jour:

Bon, maintenant que je pense que je comprends ce que vous êtes ici, voici une autre prise à ceci:

Peut-être n'avez-vous pas besoin du paramètre d'action url et devriez-vous décrire le contenu que vous recherchez d'une autre manière. Puisque vous dites que les méthodes renvoient des données de la même entité, laissez simplement les paramètres faire la description pour vous.

Par exemple, vos deux méthodes pourraient être transformées en:

public HttpResponseMessage Get()
{
    return null;
}

public HttpResponseMessage Get(MyVm vm)
{
    return null;
}

Quel type de données transmettez-vous à l'objet MyVm? Si vous pouvez simplement passer des variables via l'URI, je vous conseillerais de suivre cette voie. Sinon, vous devrez envoyer l'objet dans le corps de la requête, ce qui n'est pas très HTTP lorsque vous effectuez une opération GET (cela fonctionne cependant, utilisez simplement [FromBody] en face de MyVm).

Espérons que cela montre que vous pouvez avoir plusieurs méthodes GET dans un seul contrôleur sans utiliser le nom de l'action ni même l'attribut [HttpGet].

424
Jed

Mise à jour à partir de l'API Web 2. 

Avec cette configuration d'API dans votre fichier WebApiConfig.cs:

public static void Register(HttpConfiguration config)
{
    //// Web API routes
    config.MapHttpAttributeRoutes(); //Don't miss this

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = System.Web.Http.RouteParameter.Optional }
    );
}

Vous pouvez acheminer notre contrôleur comme ceci:

[Route("api/ControllerName/Summary")]
[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    rturn null;
}

[Route("api/ControllerName/FullDetails")]
[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}

Où ControllerName est le nom de votre contrôleur (sans "contrôleur"). Cela vous permettra d'obtenir chaque action avec l'itinéraire détaillé ci-dessus.

Pour en savoir plus: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

55
Marc Stevenson

Dans l'API Web (par défaut), les méthodes sont choisies en fonction de la combinaison de la méthode HTTP et des valeurs d'itinéraire

MyVm ressemble à un objet complexe, lu par le formateur à partir du corps, de sorte que vous disposez de deux méthodes identiques en termes de données de route (car aucun d’eux n’a aucun paramètre de la route) - ce qui empêche le répartiteur (IHttpActionSelector) de correspondre à la un approprié.

Vous devez les différencier par un paramètre de chaîne de requête ou un paramètre de route pour résoudre les ambiguïtés.

14
Filip W

Après de nombreuses recherches sur le Web et la recherche de la forme de carte de routage la mieux adaptée Si nous avons trouvé ce qui suit: 

config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id =RouteParameter.Optional }, new { id = @"\d+" });
config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");

Ces mappages s’appliquant à la fois au mappage du nom de l’action et à la convention http de base (GET, POST, PUT, DELETE) 

12
Moatasem bakri

Sans utiliser d'actions, les options seraient les suivantes:

  1. déplacez l’une des méthodes sur un autre contrôleur afin qu’elles ne s’entrechoquent pas.

  2. utilisez juste une méthode qui prend le paramètre, et si c'est null, appelez l'autre méthode à partir de votre code.

5
Joanna Derks

Il est possible que vos méthodes Web soient résolues à la même adresse URL. Regardez le lien suivant: -

http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Vous devrez donc peut-être ajouter votre nom de méthode à votre table de routage.

4
Max

J'ai constaté que lorsque j'ai deux méthodes Get, une sans paramètre et l'autre avec un type complexe en tant que paramètre, j'ai la même erreur. J'ai résolu ce problème en ajoutant un paramètre factice de type int, nommé Id, en tant que premier paramètre, suivi de mon paramètre de type complexe. J'ai ensuite ajouté le paramètre de type complexe au modèle de route. Ce qui suit a fonctionné pour moi.

D'abord obtenir:

public IEnumerable<SearchItem> Get()
{
...
}

Deuxième get:

public IEnumerable<SearchItem> Get(int id, [FromUri] List<string> layers)
{
...
}

WebApiConfig:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}/{layers}",
    defaults: new { id = RouteParameter.Optional, layers RouteParameter.Optional }
);
3
Andrew Terwiel

Cette solution a fonctionné pour moi.

Veuillez placer Route2 en premier dans WebApiConfig. Ajoutez également HttpGet et HttpPost avant chaque méthode et incluez le nom du contrôleur et le nom de la méthode dans l'URL.

WebApiConfig =>

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

Contrôleur => 

public class ValuesController : ApiController
{

    [HttpPost]
    public string GetCustomer([FromBody] RequestModel req)
    {
        return "Customer";
    }

    [HttpPost]
    public string GetCustomerList([FromBody] RequestModel req)
    {
        return "Customer List";
    }
}

Url => 

http://localhost:7050/api/Values/GetCustomer

http://localhost:7050/api/Values/GetCustomerList
3
Alan Rezende

Veuillez vérifier que vous avez deux méthodes qui portent le même nom et les mêmes paramètres. 

Si c'est le cas, supprimez n'importe quelle méthode et essayez.

2
Ramesh

Cela est possible en raison de l’utilisation du contrôleur MVC au lieu du contrôleur API Web . Vérifiez l’espace de noms dans le contrôleur API Web:

using System.Net;
using System.Net.Http;
using System.Web.Http;

Si les espaces de noms sont comme suit, alors il est donné l'erreur ci-dessus dans l'appel de la méthode du contrôleur API Web

using System.Web;
using System.Web.Mvc;
2
Ujwal Khairnar

Je suis tombé sur ce problème en essayant d’augmenter mes contrôleurs WebAPI avec des actions supplémentaires.

Suppose que tu aurais

public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

[HttpGet]
public void ReSeed()
{
    // Your custom action here
}

Il existe maintenant deux méthodes qui satisfont la demande de/api/controller qui déclenche le problème décrit par TS.

Je ne voulais pas ajouter de paramètres "factices" à mes actions supplémentaires. J'ai donc examiné les actions par défaut et en suis arrivé à:

[ActionName("builtin")]
public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

pour la première méthode en combinaison avec la liaison "double":

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "builtin", id = RouteParameter.Optional },
    constraints: new { id = @"\d+" });

config.Routes.MapHttpRoute(
    name: "CustomActionApi",
    routeTemplate: "api/{controller}/{action}");

Notez que même s'il n'y a pas de paramètre "action" dans le premier modèle de route, vous pouvez apparemment toujours configurer une action par défaut nous permettant de séparer le routage des appels Web "normaux" et des appels à l'action supplémentaire.

2

Ceci est la réponse pour tous ceux qui savent que tout est correct et qui a vérifié 50 fois .....

Assurez-vous que vous ne regardez pas à plusieurs reprises RouteConfig.cs.

Le fichier que vous souhaitez modifier s'appelle WebApiConfig.cs

En outre, il devrait probablement ressembler à ceci:

using System.Web.Http;

namespace My.Epic.Website
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
          config.MapHttpAttributeRoutes();

          // api/Country/WithStates
          config.Routes.MapHttpRoute(
            name: "ControllerAndActionOnly",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { },
            constraints: new { action = @"^[a-zA-Z]+([\s][a-zA-Z]+)*$" });

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

J'aurais pu me sauver environ 3 heures.

1
CarComp

Dans mon cas, tout allait bien

1) Web Config a été configuré correctement 2) Le préfixe de route et les attributs de route étaient appropriés

J'avais toujours l'erreur. Dans mon cas, l'attribut "Route" (en appuyant sur F12) pointait sur System.Web.MVc mais pas sur System.Web.Http, ce qui était à l'origine du problème.

0
Hemanth Vatti

Vous pouvez ajouter [Route("api/[controller]/[action]")] à votre classe de contrôleur.

[Route("api/[controller]/[action]")]
[ApiController]
public class MySuperController : ControllerBase
{
 ...
}
0
emert117

Par exemple => TestController

        [HttpGet]
        public string TestMethod(int arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod2(string arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod3(int arg0,string arg1)
        {
            return "";
        }

Si vous ne pouvez modifier que le fichier WebApiConfig.cs.

 config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/",
                defaults: null
            );

C'est tout :)

Et résultat:  enter image description here

0
Cemre Onur Baş

Assurez-vous de ne PAS décorer vos méthodes de contrôleur pour les actions par défaut GET | PUT | POST | DELETE avec l'attribut [HttpPost/Put/Get/Get]. J'avais ajouté cet attribut à l'action de mon contrôleur Vanilla Post et cela provoquait un 404. 

J'espère que cela aidera quelqu'un car cela peut être très frustrant et freiner le progrès.

0
ComeIn

Je sais que la question est ancienne, mais parfois, lorsque vous utilisez des ressources de service comme AngularJS pour vous connecter à WebAPI, assurez-vous que vous utilisez le bon chemin, sinon cette erreur se produit.

0
Suresh Kaushik

Avez-vous essayé comme:

[HttpGet("Summary")]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet("FullDetails")]
public HttpResponseMessage FullDetails()
{
    return null;
}
0
Deepak Shaw