Pouvez-vous surcharger les méthodes de contrôleur dans ASP.NET MVC?

Je suis curieux de voir si vous pouvez surcharger les méthodes de contrôleur dans ASP.NET MVC. Chaque fois que j’essaie, j’obtiens l’erreur ci-dessous. Les deux méthodes acceptent des arguments différents. Est-ce quelque chose qui ne peut pas être fait?

La requête en cours pour l’action ‘MyMethod’ sur le type de contrôleur ‘MyController’ est ambiguë entre les méthodes d’action suivantes:

    Vous pouvez utiliser l’atsortingbut si vous souhaitez que votre code effectue une surcharge.

    [ActionName("MyOverloadedName")] 

    Mais, vous devrez utiliser un nom d’action différent pour la même méthode http (comme d’autres l’ont déjà dit). Donc, ce n’est que de la sémantique à ce stade. Préféreriez-vous avoir le nom dans votre code ou votre atsortingbut?

    Phil a un article lié à ceci: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx

    Oui. J’ai pu le faire en définissant le paramètre HttpGet / HttpPost (ou l’atsortingbut équivalent AcceptVerbs ) pour chaque méthode de contrôleur sur quelque chose de distinct, à savoir HttpGet ou HttpPost , mais pas les deux. Ainsi, en fonction du type de requête, quelle méthode utiliser.

     [HttpGet] public ActionResult Show() { ... } [HttpPost] public ActionResult Show( ssortingng userName ) { ... } 

    Une suggestion que j’ai est que, pour un cas comme celui-ci, serait d’avoir une implémentation privée sur laquelle vos deux méthodes d’action publiques s’appuient pour éviter la duplication de code.

    Vous pouvez faire autre chose … vous voulez une méthode capable d’avoir un paramètre et non.

    Pourquoi ne pas essayer ça …

     public ActionResult Show( ssortingng username = null ) { ... } 

    Cela a fonctionné pour moi … et dans cette méthode, vous pouvez réellement tester si vous avez le paramètre entrant.


    Mis à jour pour supprimer la syntaxe NULL valide sur la chaîne et utiliser une valeur de paramètre par défaut.

    Non, non et non Allez et essayez le code du contrôleur ci-dessous où le “LoadCustomer” est surchargé.

     public class CustomerController : Controller { // // GET: /Customer/ public ActionResult LoadCustomer() { return Content("LoadCustomer"); } public ActionResult LoadCustomer(ssortingng str) { return Content("LoadCustomer with a ssortingng"); } } 

    Si vous essayez d’appeler l’action “LoadCustomer”, vous obtiendrez une erreur, comme indiqué dans la figure ci-dessous.

    entrer la description de l'image ici

    Le polymorphism fait partie de la programmation en C # alors que HTTP est un protocole. HTTP ne comprend pas le polymorphism. HTTP fonctionne sur le concept ou l’URL et l’URL ne peuvent avoir qu’un nom unique. Ainsi, HTTP n’implémente pas le polymorphism.

    Pour corriger cela, nous devons utiliser l’atsortingbut “ActionName”.

     public class CustomerController : Controller { // // GET: /Customer/ public ActionResult LoadCustomer() { return Content("LoadCustomer"); } [ActionName("LoadCustomerbyName")] public ActionResult LoadCustomer(ssortingng str) { return Content("LoadCustomer with a ssortingng"); } } 

    Donc maintenant, si vous appelez l’URL “Customer / LoadCustomer”, l’action “LoadCustomer” sera appelée et avec la structure d’URL “Customer / LoadCustomerByName”, “LoadCustomer (ssortingng str)” sera appelé.

    entrer la description de l'image ici

    entrer la description de l'image ici

    La réponse ci-dessus que j’ai tirée de cet article codeproject -> MVC Action surcharge

    Pour résoudre ce problème, vous pouvez écrire un ActionMethodSelectorAtsortingbute qui examine MethodInfo pour chaque action et le compare aux valeurs de formulaire publiées, puis rejette toute méthode pour laquelle les valeurs de formulaire ne correspondent pas (à l’exception du nom du bouton, bien sûr).

    Voici un exemple: – http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/

    MAIS, ce n’est pas une bonne idée.

    A ma connaissance, vous ne pouvez utiliser la même méthode qu’avec différentes méthodes http.

    c’est à dire

     [AcceptVerbs("GET")] public ActionResult MyAction() { } [AcceptVerbs("POST")] public ActionResult MyAction(FormResult fm) { } 

    Je l’ai réalisé avec l’aide du routage d’atsortingbuts dans MVC5. Certes, je suis nouveau sur MVC après une décennie de développement Web en utilisant WebForms, mais ce qui suit a fonctionné pour moi. Contrairement à la réponse acceptée, toutes les actions surchargées peuvent être rendues par le même fichier de vue.

    Activez d’abord le routage d’atsortingbuts dans App_Start / RouteConfig.cs.

     public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAtsortingbuteRoutes(); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } 

    Décorez éventuellement votre classe de contrôleur avec un préfixe de route par défaut.

     [RoutePrefix("Returns")] public class ReturnsController : BaseController { //....... 

    Décorez ensuite les actions de votre contrôleur qui se surchargent avec un itinéraire et des parameters communs. En utilisant les parameters de type contrainte, vous pouvez utiliser le même format URI avec des identifiants de différents types.

     [HttpGet] // Returns public ActionResult Index() { //..... } [HttpGet] [Route("View")] // Returns/View public ActionResult View() { // I wouldn't really do this but it proves the concept. int id = 7026; return View(id); } [HttpGet] [Route("View/{id:int}")] // Returns/View/7003 public ActionResult View(int id) { //..... } [HttpGet] [Route("View/{id:Guid}")] // Returns/View/99300046-0ba4-47db-81bf-ba6e3ac3cf01 public ActionResult View(Guid id) { //..... } 

    J’espère que cela aide et ne conduit pas quelqu’un sur le mauvais chemin. 🙂

    Vous pouvez utiliser un seul ActionResult pour traiter à la fois les ActionResult et les ActionResult :

     public ActionResult Example() { if (Request.HttpMethod.ToUpperInvariant() == "GET") { // GET } else if (Request.HttpMethod.ToUpperInvariant() == "POST") { // Post } } 

    Utile si vos méthodes Get et Post ont des signatures correspondantes.

    Je viens de tomber sur cette question et, même si elle est assez ancienne maintenant, elle est toujours très pertinente. Ironiquement, le seul commentaire correct dans cette discussion a été posté par un débutant avoué dans MVC quand il a écrit le post. Même les documents ASP.NET ne sont pas tout à fait corrects. J’ai un grand projet et je réussis à surcharger les méthodes d’action.

    Si l’on comprend le routage, au-delà du modèle de route par défaut {controller} / {action} / {id}, il peut être évident que les actions du contrôleur peuvent être mappées en utilisant n’importe quel modèle unique. Quelqu’un ici a parlé de polymorphism et a déclaré: “HTTP ne comprend pas le polymorphism”, mais le routage n’a rien à voir avec HTTP. Il s’agit simplement d’un mécanisme de correspondance de motifs de chaînes.

    La meilleure façon de faire ce travail consiste à utiliser les atsortingbuts de routage, par exemple:

     [RoutePrefix("cars/{country:length(3)}")] public class CarHireController { [Route("{location}/{page:int=1}", Name = "CarHireLocation")] public ActionResult Index(ssortingng country, ssortingng location, int page) { return Index(country, location, null, page); } [Route("{location}/{subLocation}/{page:int=1}", Name = "CarHireSubLocation")] public ActionResult Index(ssortingng country, ssortingng location, ssortingng subLocation, int page) { //The main work goes here } } 

    Ces actions prendront en charge les URL telles que /cars/usa/new-york et /cars/usa/texas/dallas , qui correspondront respectivement aux première et deuxième actions de l’index.

    En examinant cet exemple de contrôleur, il est évident qu’il va au-delà du modèle de route par défaut mentionné ci-dessus. La valeur par défaut fonctionne bien si votre structure d’URL correspond exactement à vos conventions d’atsortingbution de noms de code, mais ce n’est pas toujours le cas. Le code doit être descriptif du domaine, mais les URL doivent souvent aller plus loin car leur contenu doit être basé sur d’autres critères, tels que les exigences de référencement.

    L’avantage du modèle de routage par défaut est qu’il crée automatiquement des itinéraires uniques. Ceci est appliqué par le compilateur car les URL correspondent aux types de contrôleur et aux membres uniques. Rouler vos propres modèles de route nécessitera une reflection attentive pour assurer l’unicité et le bon fonctionnement.

    Remarque importante L’inconvénient est que l’utilisation du routage pour générer des URL pour les actions surchargées ne fonctionne pas sur la base d’un nom d’action, par exemple, lors de l’utilisation de UrlHelper.Action. Mais cela fonctionne si on utilise des routes nommées, par exemple UrlHelper.RouteUrl. Selon des sources respectées, l’utilisation des routes nommées est la voie à suivre ( http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/ ).

    Bonne chance!

    J’avais besoin d’une surcharge pour:

     public ActionResult Index(ssortingng i); public ActionResult Index(int groupId, int itemId); 

    Il y avait peu d’arguments où j’ai fini par faire ça:

     public ActionResult Index(ssortingng i, int? groupId, int? itemId) { if (!ssortingng.IsNullOrWhitespace(i)) { // parse i for the id } else if (groupId.HasValue && itemId.HasValue) { // use groupId and itemId for the id } } 

    Ce n’est pas une solution parfaite, surtout si vous avez beaucoup d’arguments, mais cela fonctionne bien pour moi.

    J’ai également rencontré le même problème dans mon application. Sans modifier aucune information sur les méthodes, j’ai fourni [ActionName (“SomeMeaningfulName”)] sur la tête Action. problème résolu

     [ActionName("_EmployeeDetailsByModel")] public PartialViewResult _EmployeeDetails(Employee model) { // Some Operation return PartialView(model); } } [ActionName("_EmployeeDetailsByModelWithPagination")] public PartialViewResult _EmployeeDetails(Employee model,int Page,int PageSize) { // Some Operation return PartialView(model); } 

    Vous pouvez utiliser [ActionName (“NewActionName”)] pour utiliser la même méthode avec un nom différent:

     public class HomeController : Controller { public ActionResult GetEmpName() { return Content("This is the test Message"); } [ActionName("GetEmpWithCode")] public ActionResult GetEmpName(ssortingng EmpCode) { return Content("This is the test Messagewith Overloaded"); } } 

    Créer la méthode de base comme virtuelle

     public virtual ActionResult Index() 

    Créez la méthode remplacée en tant que substitution

     public override ActionResult Index() 

    Edit: Cela ne s’applique évidemment que si la méthode de substitution est dans une classe dérivée qui semble ne pas avoir été l’intention de l’OP.

    J’aime cette réponse postée dans un autre fil de discussion

    Ceci est principalement utilisé si vous héritez d’un autre contrôleur et souhaitez remplacer une action du contrôleur de base

    ASP.NET MVC – Remplacement d’une action avec des parameters différents

    Une seule signature publique est autorisée pour chaque méthode de contrôleur. Si vous essayez de le surcharger, il sera compilé, mais vous obtenez l’erreur d’exécution que vous avez rencontrée.

    Si vous ne souhaitez pas utiliser différents verbes (comme les [HttpGet] et [HttpPost] ) pour différencier les méthodes surchargées (qui fonctionneront), ou modifier le routage, il ne vous rest plus qu’à fournir une autre méthode avec nom différent, ou vous pouvez envoyer à l’intérieur de la méthode existante. Voici comment je l’ai fait:

    Je suis arrivé une fois dans une situation où je devais maintenir la compatibilité ascendante. La méthode d’origine prévoyait deux parameters, mais le nouveau n’en avait qu’un. La surcharge telle que je m’y attendais ne fonctionnait pas car MVC n’avait plus trouvé le point d’entrée.

    Pour résoudre ce problème, j’ai fait ce qui suit:

    1. Changement des 2 méthodes d’action surchargées de public à privé
    2. Création d’une nouvelle méthode publique contenant “seulement” 2 parameters de chaîne. Celui-ci a agi en tant que répartiteur, à savoir:

       public ActionResult DoSomething(ssortingng param1, ssortingng param2) { if (ssortingng.IsNullOrEmpty(param2)) { return DoSomething(ProductName: param1); } else { int oldId = int.Parse(param1); return DoSomething(OldParam: param1, OldId: oldId); } } private ActionResult DoSomething(ssortingng OldParam, int OldId) { // some code here return Json(result); } private ActionResult DoSomething(ssortingng ProductName) { // some code here return Json(result); } 

    Bien sûr, ceci est un hack et devrait être refait plus tard. Mais pour le moment, cela a fonctionné pour moi.

    Vous pouvez également créer un répartiteur comme:

     public ActionResult DoSomething(ssortingng action, ssortingng param1, ssortingng param2) { switch (action) { case "update": return UpdateAction(param1, param2); case "remove": return DeleteAction(param1); } } 

    Vous pouvez voir que UpdateAction a besoin de 2 parameters, tandis que DeleteAction en a juste besoin d’un.

    S’il s’agit d’une tentative d’utilisation d’une action GET pour plusieurs vues POST vers plusieurs actions avec des modèles différents, essayez d’append une action GET pour chaque action POST qui redirige vers le premier GET pour empêcher 404 lors de l’actualisation.

    Plan long mais scénario commun.