Können Sie Controller-Methoden in ASP.NET MVC überlasten?
-
22-07-2019 - |
Frage
Ich bin gespannt zu sehen, ob Sie Controller-Methoden in ASP.NET MVC überlasten. Jedes Mal, wenn ich versuche, erhalte ich die Fehlermeldung unten. Die beiden Methoden akzeptieren verschiedene Argumente. Ist dies etwas, das nicht getan werden kann?
Die aktuelle Handlungsaufforderung ‚MyMethod‘ auf Regler Typ ‚MyController‘ mehrdeutig ist zwischen den folgenden Aktionsmethoden:
Lösung
Sie können das Attribut verwenden, wenn Sie Ihren Code wollen Überlastung tun.
[ActionName("MyOverloadedName")]
Aber, werden Sie eine andere Aktion Namen für die gleiche http-Methode verwenden müssen (wie andere gesagt haben). So ist es nur Semantik an diesem Punkt. Möchten Sie lieber den Namen haben in Ihrem Code oder Ihr Attribut?
Andere Tipps
Ja. Ich habe in der Lage, dies zu tun, indem Sie das HttpGet
/ HttpPost
Einstellung (oder gleichwertig AcceptVerbs
Attributs) für jede Controller-Methode, um etwas deutlich, das heißt, HttpGet
oder HttpPost
, aber nicht beides. Auf diese Weise kann es von der Art der Anfrage basiert sagen, welche Methode zu verwenden.
[HttpGet]
public ActionResult Show()
{
...
}
[HttpPost]
public ActionResult Show( string userName )
{
...
}
Ein Vorschlag, den ich habe, ist, dass für einen Fall wie diesen, eine private Implementierung zu haben wäre, die beide Ihrer öffentlichen Aktion Methoden verlassen Duplizieren Code zu vermeiden.
Hier ist etwas, was Sie tun können ... Sie eine Methode wollen, die einen Parameter zu haben, ist in der Lage und nicht.
Warum nicht versuchen ...
public ActionResult Show( string username = null )
{
...
}
Das hat für mich gearbeitet ... und in diesem Verfahren, können Sie tatsächlich testen, um zu sehen, ob Sie die eingehenden Parameter haben.
Aktualisierte die ungültige Nullable-Syntax auf Zeichenfolge zu entfernen und einen Standardparameterwert verwendet werden.
Nein, Nein und Nein. Go und versuchen, den Controller-Code unten, wo wir haben die „LoadCustomer“ überlastet.
public class CustomerController : Controller
{
//
// GET: /Customer/
public ActionResult LoadCustomer()
{
return Content("LoadCustomer");
}
public ActionResult LoadCustomer(string str)
{
return Content("LoadCustomer with a string");
}
}
Wenn Sie versuchen, die „LoadCustomer“ Aktion aufrufen Sie Fehler erhalten werden, wie in der folgenden Abbildung dargestellt.
Polymorphismus ist ein Teil der C # -Programmierung, während HTTP ist ein Protokoll. HTTP nicht Polymorphismus verstehen. HTTP arbeitet auf dem Konzept des oder die URL und URL nur eindeutigen Namen hat. So HTTP nicht Polymorphismus implementieren.
Um das gleiche zu beheben wir brauchen „Action“ Attribut verwenden.
public class CustomerController : Controller
{
//
// GET: /Customer/
public ActionResult LoadCustomer()
{
return Content("LoadCustomer");
}
[ActionName("LoadCustomerbyName")]
public ActionResult LoadCustomer(string str)
{
return Content("LoadCustomer with a string");
}
}
So, jetzt, wenn Sie einen Anruf URL „Customer / LoadCustomer“ machen die „LoadCustomer“ Aktion wird die „LoadCustomer (string str)“ wird aufgerufen aufgerufen und mit URL-Struktur „Customer / LoadCustomerByName“ werden.
Die obige Antwort, die ich von diesem Artikel Codeproject genommen habe -> MVC Aktion Überlastung
Um dieses Problem zu überwinden Sie können schreiben Sie eine ActionMethodSelectorAttribute
, die die MethodInfo
für jede Aktion untersucht und vergleicht sie mit den gebuchten Formularwerte und lehnt dann jede Methode, für die die Form Werte nicht übereinstimmen (ausgenommen die Schaltfläche Name, natürlich).
Hier ist ein Beispiel: - http: // blog. abodit.com/2010/02/asp-net-mvc-ambiguous-match/
Aber dies ist keine gute Idee.
Soweit ich weiß, Sie können nur die gleiche Methode haben, wenn verschiedene HTTP-Methoden verwenden.
d.
[AcceptVerbs("GET")]
public ActionResult MyAction()
{
}
[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{
}
Ich habe dies mit Hilfe von Attribut Routing in MVC5. Ich bin zugegebenermaßen neu zu MVC von einem Jahrzehnt der Web-Entwicklung kommt mit WebForms, aber folgendes hat für mich gearbeitet. Im Gegensatz zu der akzeptierten Antwort ermöglicht diese alle überlasteten Aktionen durch die gleiche Ansicht Datei gerendert werden.
Erstes Attribut ermöglichen Routing App_Start / RouteConfig.cs.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Optional Ihre Controller-Klasse mit einer Standardroute Präfix dekoriert.
[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
//.......
Dann wird Ihre Controller-Aktionen dekorieren, die sie mit einem gemeinsamen Weg und Parametern überlasteten anzupassen. Unter Verwendung von Typ beschränkte Parameter können Sie das gleiche URI-Format mit IDs von verschiedenen Typen verwendet werden.
[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)
{
//.....
}
Hope, das hilft und den falschen Weg nicht was jemand nach unten. : -)
Sie können einen einzelnen ActionResult
verwenden zu behandeln sowohl Post
und Get
:
public ActionResult Example() {
if (Request.HttpMethod.ToUpperInvariant() == "GET") {
// GET
}
else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
// Post
}
}
Nützlich, wenn Ihr Get
und Post
Methoden haben passende Signaturen.
Ich habe gerade über diese Frage kommen und, auch wenn es jetzt schon recht alt ist, es ist immer noch sehr relevant. Ironischerweise wurde der ein richtiger Kommentar in diesem Thread von einem bekennenden Anfänger in MVC geschrieben, als er den Beitrag schrieb. Auch die ASP.NET-Dokumentation nicht ganz korrekt. Ich habe ein großes Projekt und ich überlastete erfolgreich Aktionsmethoden.
Wenn ein Routing versteht, über die einfache {Controller} / {Aktion} / {id} Standardroute Muster, könnte es offensichtlich sein, dass Controller-Aktionen unter Verwendung eines beliebigen eindeutigen Muster abgebildet werden können. Jemand hier sprach über Polymorphismus und sagte: „HTTP nicht versteht Polymorphismus“, aber Routing hat nichts mit HTTP zu tun. Es ist, einfach ausgedrückt, ein Mechanismus für die Zeichenfolge Mustervergleich.
Der beste Weg, um diese Arbeit zu machen, ist die Routing-Attribute zu verwenden, zum Beispiel:
[RoutePrefix("cars/{country:length(3)}")]
public class CarHireController
{
[Route("{location}/{page:int=1}", Name = "CarHireLocation")]
public ActionResult Index(string country, string location, int page)
{
return Index(country, location, null, page);
}
[Route("{location}/{subLocation}/{page:int=1}", Name = "CarHireSubLocation")]
public ActionResult Index(string country, string location, string subLocation, int page)
{
//The main work goes here
}
}
Diese Aktionen kümmern Urls wie /cars/usa/new-york
und /cars/usa/texas/dallas
, die jeweils mit den ersten und zweiten Index Aktionen abbildet.
Untersuchen dieses Beispiel Controller es offensichtlich ist, dass es über die Standardroute Muster oben erwähnt geht. Der Standard funktioniert gut, wenn Sie Ihre URL-Struktur entspricht genau Ihren Code Namenskonvention, aber dies ist nicht immer der Fall. Code sollte der Domain beschreibend sein, aber Urls müssen oft weiter gehen, weil ihr Inhalt auf der Grundlage anderer Kriterien werden sollte, wie SEO-Anforderungen.
Der Vorteil des Standard-Routing-Musters ist, dass es automatisch erstellt einzigartige Routen. Dies wird durch den Compiler erzwungen, da Urls einzigartige Controller-Typen und Mitglieder übereinstimmen. Ihre eigenen Leitwegschemata rollen wird sorgfältiges Nachdenken erfordern Eindeutigkeit zu gewährleisten und dass sie funktionieren.
Wichtiger Hinweis: Der einzige Nachteil ist, dass Routing unter Verwendung von URLs für überladene Aktionen zu generieren funktionieren nicht, wenn auf einem Aktionsnamen basiert, beispielsweise wenn UrlHelper.Action verwenden. Aber es funktioniert, wenn man benannte Routen verwendet, zum Beispiel UrlHelper.RouteUrl. Und benannte Routen verwenden, ist nach angesehenen Quellen, die Art und Weise irgendwie zu gehen ( http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/ ).
Viel Glück!
Sie können [Action ( „NewActionName“)] die gleiche Methode mit einem anderen Namen zu verwenden:
public class HomeController : Controller
{
public ActionResult GetEmpName()
{
return Content("This is the test Message");
}
[ActionName("GetEmpWithCode")]
public ActionResult GetEmpName(string EmpCode)
{
return Content("This is the test Messagewith Overloaded");
}
}
Ich brauchte eine Überlastung für:
public ActionResult Index(string i);
public ActionResult Index(int groupId, int itemId);
Es gab nur wenige genug Argumente, wo ich dies am Ende tun:
public ActionResult Index(string i, int? groupId, int? itemId)
{
if (!string.IsNullOrWhitespace(i))
{
// parse i for the id
}
else if (groupId.HasValue && itemId.HasValue)
{
// use groupId and itemId for the id
}
}
Es ist keine perfekte Lösung, vor allem, wenn Sie eine Menge Argumente haben, aber es funktioniert gut für mich.
Auch ich habe gleiches Problem in meiner Anwendung konfrontiert. Ohne Modifiyig keine Informationen Methode, ich habe bereitgestellt [Action ( „SomeMeaningfulName“)] auf dem Kopf Aktion. Problem behoben
[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);
}
Erstellen Sie die Basismethode als virtuelle
public virtual ActionResult Index()
Erstellen Sie die überschriebene Methode als Überschreibung
public override ActionResult Index()
Edit:. Dies gilt natürlich nur dann, wenn die Überschreibung Methode in einer abgeleiteten Klasse ist, die nicht zu haben scheinen gewesen Absicht des OPs
Ich mag diese Antwort in einem anderen Thread geschrieben
Dies wird vor allem verwendet, wenn Sie von einem anderen Controller erben und wollen eine acction von der Basissteuerung außer Kraft zu setzen
ASP.NET MVC - eine Aktion mit unterschiedlichen Parametern Aufschalten
Es gibt nur eine öffentliche Signatur für jede Controller-Methode erlaubt. Wenn Sie versuchen, es zu überlasten, wird es kompilieren, aber Sie zum Laufzeitfehler Sie erlebt haben.
Wenn Sie nicht bereit sind, verschiedene Verben zu verwenden (wie die [HttpGet]
und [HttpPost]
Attribute) ladenen Methoden zu unterscheiden (die funktioniert) oder das Routing ändern, was dann bleibt, ist, dass Sie entweder eine andere Methode mit einem anderen zur Verfügung stellen kann nennen, oder Sie können innerhalb der bestehenden Methode versenden. Hier ist, wie ich es getan hätte:
Ich kam einmal in eine Situation, wo ich Kompatibilität hatte aufrechtzuerhalten rückwärts. Die ursprüngliche Methode erwartet zwei Parameter, aber der neue hatte nur einen. Überlastungen der Art, wie ich funktionierte nicht zu erwarten, da MVC nicht den Einstiegspunkt nicht mehr gefunden werden.
Um das zu lösen, habe ich die folgenden:
- geändert, um die zwei überladene Aktionsmethoden von öffentlichen zu privaten
-
Erstellt eine neue öffentliche Methode, die „nur“ 2-String-Parameter enthalten. Dass man agierte als Dispatcher, das heißt:.
public ActionResult DoSomething(string param1, string param2) { if (string.IsNullOrEmpty(param2)) { return DoSomething(ProductName: param1); } else { int oldId = int.Parse(param1); return DoSomething(OldParam: param1, OldId: oldId); } } private ActionResult DoSomething(string OldParam, int OldId) { // some code here return Json(result); } private ActionResult DoSomething(string ProductName) { // some code here return Json(result); }
Natürlich ist dies ein Hack und soll später überarbeitet werden. Aber für den Augenblick, es funktionierte für mich.
Sie können auch einen Dispatcher wie erstellen
public ActionResult DoSomething(string action, string param1, string param2)
{
switch (action)
{
case "update":
return UpdateAction(param1, param2);
case "remove":
return DeleteAction(param1);
}
}
Sie können sehen, dass Update 2 Parameter benötigt, während DeleteAction man gerade braucht.
Wenn dies ist ein Versuch, eine GET-Aktion für mehrere Ansichten zu verwenden, die mit verschiedenen Modellen, um mehrere Aktionen POST, dann versuchen Sie eine GET-Aktion für jede POST Aktion hinzufügen, die mit dem ersten GET umleitet 404 auf Refresh zu verhindern.
Langer Schuss aber gängiges Szenario.