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:

War es hilfreich?

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?

Phil hat einen Artikel im Zusammenhang mit diesem:

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.

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:

  1. geändert, um die zwei überladene Aktionsmethoden von öffentlichen zu privaten
  2. 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top