GET- und POST-Methoden mit demselben Aktionsnamen im selben Controller [Duplikat]

78

Warum ist das falsch?

{
    public class HomeController : Controller
    {

        [HttpGet]
        public ActionResult Index()
        {
            Some Code--Some Code---Some Code
            return View();
        }

        [HttpPost]
        public ActionResult Index()
        {
            Some Code--Some Code---Some Code
            return View();
        }

    }

Wie kann ich einen Controller haben, der eine Sache beantwortet, wenn "getted" und eine, wenn "gebucht" wird?

Ricardo Polo Jaramillo
quelle

Antworten:

176

Da Sie nicht zwei Methoden mit demselben Namen und derselben Signatur haben können, müssen Sie das folgende ActionNameAttribut verwenden:

[HttpGet]
public ActionResult Index()
{
  // your code
  return View();
}

[HttpPost]
[ActionName("Index")]
public ActionResult IndexPost()
{
  // your code
  return View();
}

Siehe auch "Wie aus einer Methode eine Aktion wird"

Glasscherben
quelle
Ich weiß, es ist zu spät zu fragen. Es ist jedoch möglich, zwei verschiedene HttpPost-Aktionsmethoden mit demselben Namen zu verwenden, die unterschiedliche Parameter annehmen. Ich spreche von einem Fall, in dem ich Filter auf eine Erstellungsmethode anwenden muss, für die bereits eine HttpPost-Methode definiert ist
Vini
Ja, dies ist möglich, da es sich um eine gültige .Net-Methodensignatur handelt. Die Methoden sind überladen (Methodenüberladung).
Nwolisa
37

Während Sie mit ASP.NET MVC zwei Aktionen mit demselben Namen ausführen können, können Sie mit .NET nicht zwei Methoden mit derselben Signatur verwenden, dh denselben Namen und dieselben Parameter.

Sie müssen die Methoden unterschiedlich benennen. Verwenden Sie das ActionName-Attribut, um ASP.NET MVC mitzuteilen, dass es sich tatsächlich um dieselbe Aktion handelt.

Wenn Sie jedoch von einem GET und einem POST sprechen, wird dieses Problem wahrscheinlich behoben, da die POST-Aktion mehr Parameter als die GET benötigt und daher unterscheidbar ist.

Sie benötigen also entweder:

[HttpGet]
public ActionResult ActionName() {...}

[HttpPost, ActionName("ActionName")]
public ActionResult ActionNamePost() {...}

Oder,

[HttpGet]
public ActionResult ActionName() {...}

[HttpPost]
public ActionResult ActionName(string aParameter) {...}

quelle
1
Für die Aktion "Löschen" für GET und POST ist beispielsweise eine ID erforderlich. GET zum Anzeigen der Daten und POST zum Löschen. In diesem Fall muss ich ActionName
Xeuron
17

Ich akzeptiere gerne einen Formularbeitrag für meine POST-Aktionen, auch wenn ich ihn nicht benötige. Für mich ist es einfach das Richtige, wenn Sie angeblich etwas posten .

public class HomeController : Controller
{
    public ActionResult Index()
    {
        //Code...
        return View();
    }

    [HttpPost]
    public ActionResult Index(FormCollection form)
    {
        //Code...
        return View();
    }
}
scherz
quelle
1
Das einzige Problem ist, dass dies die gestrahlte HttpRequestValidationException auslöst, selbst wenn [AllowHtml] usw. Nicht, dass es eine schlechte Ausnahme ist, aber ihre Implementierung und wann sie ausgelöst wird (und insbesondere wenn sie in einem Bereich ausgelöst wird), ist unnötig undurchsichtig.
Ted
5

Um Ihre spezifische Frage zu beantworten, können Sie nicht zwei Methoden mit demselben Namen und denselben Argumenten in einer einzelnen Klasse haben. Die Verwendung der Attribute HttpGet und HttpPost unterscheidet die Methoden nicht.

Um dies zu beheben, füge ich normalerweise das Ansichtsmodell für das Formular hinzu, das Sie veröffentlichen:

public class HomeController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        Some Code--Some Code---Some Code
        return View();
    }

    [HttpPost]
    public ActionResult Index(formViewModel model)
    {
        do work on model --
        return View();
    }

}
Jeff Siver
quelle
3

Sie haben die gute Antwort auf diese Frage erhalten, aber ich möchte meine zwei Cent hinzufügen. Sie können eine Methode verwenden und Anforderungen entsprechend dem Anforderungstyp verarbeiten:

public ActionResult Index()
{
    if("GET"==this.HttpContext.Request.RequestType)
    {
        Some Code--Some Code---Some Code for GET
    }
    else if("POST"==this.HttpContext.Request.RequestType)
    {
        Some Code--Some Code---Some Code for POST
    }
    else
    {
        //exception
    }

    return View();
}
RredCat
quelle
2

Kann nicht mehrere Aktionen gleichen Namens und gleichen Parameters

    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }
    [HttpPost]
    public ActionResult Index(int id)
    {
        return View();
    }

obwohl int id nicht verwendet wird

Mason
quelle
2

Sie können nicht mehrere Aktionen mit demselben Namen ausführen. Sie könnten einer Methode einen Parameter hinzufügen, und das wäre gültig. Zum Beispiel:

    public ActionResult Index(int i)
    {
        Some Code--Some Code---Some Code
        return View();
    }

Es gibt einige Möglichkeiten, Aktionen auszuführen, die sich nur durch das Anforderungsverb unterscheiden. Mein Favorit und meiner Meinung nach am einfachsten zu implementieren ist die Verwendung des AttributeRouting- Pakets. Nach der Installation fügen Sie Ihrer Methode einfach ein Attribut wie folgt hinzu:

  [GET("Resources")]
  public ActionResult Index()
  {
      return View();
  }

  [POST("Resources")]
  public ActionResult Create()
  {
      return RedirectToAction("Index");
  }

Im obigen Beispiel haben die Methoden unterschiedliche Namen, aber der Aktionsname lautet in beiden Fällen "Ressourcen". Der einzige Unterschied ist das Anforderungsverb.

Das Paket kann mit NuGet wie folgt installiert werden:

PM> Install-Package AttributeRouting

Wenn Sie die Abhängigkeit von den AttributeRouting-Paketen nicht möchten, können Sie dies tun, indem Sie ein benutzerdefiniertes Aktionsauswahlattribut schreiben.

Kennzeichen
quelle
0

Heute habe ich einige Ressourcen zu derselben Frage überprüft und ein sehr interessantes Beispiel erhalten.

Es ist möglich, dieselbe Methode über das GET- und das POST-Protokoll aufzurufen , aber Sie müssen die Parameter wie folgt überladen:

@using (Ajax.BeginForm("Index", "MyController", ajaxOptions, new { @id = "form-consulta" }))
{
//code
}

Die Aktion:

[ActionName("Index")]
public async Task<ActionResult> IndexAsync(MyModel model)
{
//code
}

Standardmäßig ist eine Methode ohne explizites Protokoll GET. In diesem Fall gibt es jedoch einen deklarierten Parameter, mit dem die Methode wie ein POST funktioniert.

Wenn GET ausgeführt wird, spielt der Parameter keine Rolle, aber wenn POST ausgeführt wird, ist der Parameter für Ihre Anforderung erforderlich.

Moacir
quelle