341 Stimmen

Können Sie Controller-Methoden in ASP.NET MVC überladen?

Ich bin neugierig zu sehen, ob Sie Controller-Methoden in ASP.NET MVC überladen können. Immer, wenn ich es versuche, erhalte ich den folgenden Fehler. Die beiden Methoden akzeptieren unterschiedliche Argumente. Ist dies etwas, das nicht getan werden kann?

Die aktuelle Anfrage für die Aktion "MyMethod" auf dem Controllertyp "MyController" ist mehrdeutig zwischen den folgenden Aktionsmethoden:

14voto

keeney Punkte 873

Soweit ich weiß, kann man nur die gleiche Methode verwenden, wenn man verschiedene http-Methoden benutzt.

d.h.

[AcceptVerbs("GET")]
public ActionResult MyAction()
{

}

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

}

11voto

cookdn Punkte 368

Dies habe ich erreicht mit Hilfe von Attribut-Routing in MVC5. Zugegeben, ich bin neu in MVC aus einem Jahrzehnt der Web-Entwicklung mit WebForms kommen, aber das folgende hat für mich gearbeitet. Anders als die akzeptierte Antwort ermöglicht dies alle überladenen Aktionen durch die gleiche Ansichtsdatei gerendert werden.

Aktivieren Sie zunächst das Attribut Routing in 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 können Sie Ihre Controller-Klasse mit einem Standard-Routenpräfix ausstatten.

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

Dann dekorieren Sie Ihre Controller-Aktionen, die sich gegenseitig überladen, mit einer gemeinsamen Route und passenden Parametern. Mit typenbeschränkten Parametern können Sie dasselbe URI-Format mit IDs unterschiedlicher Typen verwenden.

[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)
{
    //.....
}

Ich hoffe, das hilft und führt niemanden auf den falschen Weg :-)

5voto

DevDave Punkte 6491

Sie könnten eine einzelne ActionResult mit beidem umzugehen Post y Get :

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

Nützlich, wenn Ihr Get y Post Methoden haben übereinstimmende Signaturen.

5voto

DvS Punkte 1008

Ich bin gerade auf diese Frage gestoßen, und auch wenn sie schon ziemlich alt ist, ist sie immer noch sehr aktuell. Ironischerweise wurde der einzige richtige Kommentar in diesem Thread von einem bekennenden MVC-Anfänger gepostet, als er den Beitrag schrieb. Selbst die ASP.NET-Dokumente sind nicht ganz korrekt. Ich habe ein großes Projekt und überlaste erfolgreich Aktionsmethoden.

Wenn man das Routing versteht, das über das einfache Standard-Routenmuster {controller}/{action}/{id} hinausgeht, dürfte es offensichtlich sein, dass Controller-Aktionen mit einem beliebigen eindeutigen Muster abgebildet werden können. Jemand hat hier über Polymorphismus gesprochen und gesagt: "HTTP versteht keinen Polymorphismus", aber Routing hat nichts mit HTTP zu tun. Es ist, einfach ausgedrückt, ein Mechanismus zum Abgleich von Stringmustern.

Am besten funktioniert dies, wenn Sie beispielsweise die Routing-Attribute verwenden:

[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 sich um Urls wie /cars/usa/new-york y /cars/usa/texas/dallas die der ersten bzw. zweiten Indexaktion zugeordnet werden.

Bei der Prüfung dieses Beispiels wird deutlich, dass es über das oben erwähnte Standard-Routenmuster hinausgeht. Der Standard funktioniert gut, wenn Ihre URL-Struktur genau mit Ihren Code-Namenskonventionen übereinstimmt, aber das ist nicht immer der Fall. Der Code sollte die Domäne beschreiben, aber die URLs müssen oft weiter gehen, weil ihr Inhalt auf anderen Kriterien basieren sollte, z. B. auf SEO-Anforderungen.

Der Vorteil des Standard-Routing-Musters ist, dass es automatisch eindeutige Routen erstellt. Dies wird durch den Compiler erzwungen, da die URLs eindeutigen Controllertypen und -mitgliedern entsprechen. Die Erstellung eigener Routing-Muster erfordert sorgfältige Überlegungen, um die Einzigartigkeit zu gewährleisten und sicherzustellen, dass sie funktionieren.

Wichtiger Hinweis Der einzige Nachteil ist, dass die Verwendung von Routing zur Generierung von URLs für überladene Aktionen nicht funktioniert, wenn diese auf einem Aktionsnamen basieren, z. B. bei Verwendung von UrlHelper.Action. Aber es funktioniert, wenn man benannte Routen verwendet, z.B. UrlHelper.RouteUrl. Und die Verwendung von benannten Routen ist laut angesehenen Quellen ohnehin der richtige Weg ( http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/ ).

Viel Glück!

4voto

Sie können [ActionName("NewActionName")] verwenden, um 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");
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X