MVC, deren Senden-Taste gedrückt wurde

127

Ich habe zwei Schaltflächen in meinem MVC-Formular:

<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

Woher weiß ich aus meiner Controller-Aktion, welche gedrückt wurden?

Kupfermühle
quelle
Warum nicht einfach Onclick-Ereignisse zu diesen Schaltflächen hinzufügen, die zu ihrem eigenen AJAX-Aufruf führen, der zu den entsprechenden Methoden führt? dh : <input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" />?
Ragerory

Antworten:

168

Benennen Sie beide Senden-Schaltflächen gleich

<input name="submit" type="submit" id="submit" value="Save" />
<input name="submit" type="submit" id="process" value="Process" />

Dann erhalten Sie in Ihrem Controller den Wert von submit. Nur die angeklickte Schaltfläche übergibt ihren Wert.

public ActionResult Index(string submit)
{
    Response.Write(submit);
    return View();
}

Sie können diesen Wert natürlich bewerten, um verschiedene Operationen mit einem Schalterblock auszuführen.

public ActionResult Index(string submit)
{
    switch (submit)
    {
        case "Save":
            // Do something
            break;
        case "Process":
            // Do something
            break;
        default:
            throw new Exception();
            break;
    }

    return View();
}
WDuffy
quelle
13
Beachten Sie die Probleme, die die Lokalisierung für diese Lösung mit sich bringen könnte, für die Darins Lösung nicht anfällig ist.
Richard Szalay
Zwei Eingaben mit demselben Namen führen dazu, dass ein Array mit einem Element für jeden Wert und nicht wie impliziert mit einem einzelnen Wert gebucht wird. Ich wünschte, ich könnte etwas anderes sagen, da ich gehofft / versucht habe, dies zu nutzen, aber das funktioniert nicht.
Christopher King
1
@RichardSzalay - können Sie nicht einfach <button type="submit" name="action" value="draft"> Internationalized Save Text </button>für i18n-Zwecke verwenden, sodass die dem Benutzer zugewandte Zeichenfolge anpassbar ist und Formularelementnamen niemals direkt dem Benutzer
angezeigt werden
48
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

Und in Ihrer Controller-Aktion:

public ActionResult SomeAction(string submit)
{
    if (!string.IsNullOrEmpty(submit))
    {
        // Save was pressed
    }
    else
    {
        // Process was pressed
    }
}
Darin Dimitrov
quelle
1
Ich stelle mir vor, dass weitere Schaltflächen hinzugefügt werden könnten, indem sie einfach zur Parameterliste hinzugefügt und korrekt benannt werden. Schöne Lösung!
GONeale
35

Dies ist eine bessere Antwort, sodass wir sowohl Text als auch Wert für eine Schaltfläche haben können:

http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx

</p>
<button name="button" value="register">Register</button>
<button name="button" value="cancel">Cancel</button>
</p>

und der Controller:

public ActionResult Register(string button, string userName, string email, string password, string confirmPassword)
{
if (button == "cancel")
    return RedirectToAction("Index", "Home");
...

Kurz gesagt, es ist eine SUBMIT-Schaltfläche, aber Sie wählen den Namen mithilfe des Namensattributs. Dies ist sogar noch leistungsfähiger, da Sie nicht an den Namen Submit oder die Schaltfläche in den Parametern der Controller-Methode gebunden sind. Sie können ihn nach Belieben aufrufen.

Yakir Manor
quelle
Danke Sir, das ist genau das, was ich brauche
oHoodie
Dies bricht ab, wenn Sie ein mehrsprachiges System haben, das den Wert der Schaltfläche je nach Sprache ändert.
Dave Tapson
Dave - Ich glaube nicht, dass irgendjemand ein solches System codieren würde. Das ist so, als würden Sie Ihre Controller- oder Funktionsnamen lokalisieren. Der Wert der Schaltfläche ist nur für die Verwendung auf der Serverseite bestimmt. Sie wird nirgendwo angezeigt und muss nicht lokalisiert werden.
NickG
20

Sie können Ihre Schaltfläche anhand des Namensschilds wie unten identifizieren. Sie müssen dies in Ihrem Controller überprüfen

if (Request.Form["submit"] != null)
{
//Write your code here
}
else if (Request.Form["process"] != null)
{
//Write your code here
}
Kinjal Gohil
quelle
Dies ist sehr hilfreich in Situationen, in denen Sie den Namen der Schaltfläche nicht an das Ergebnis nach der Aktion übergeben möchten.
Yogihosting
In diesem Szenario kann es komplizierter sein, die Anforderungsklasse im Komponententest zu verspotten.
Muflix
6

Hier ist eine wirklich schöne und einfache Möglichkeit, dies mit wirklich einfach zu befolgenden Anweisungen unter Verwendung eines benutzerdefinierten MultiButtonAttribute zu tun:

http://blog.maartenballiauw.be/post/2009/11/26/Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx

Um es zusammenzufassen, machen Sie Ihre Senden-Schaltflächen wie folgt:

<input type="submit" value="Cancel" name="action" />
<input type="submit" value="Create" name="action" /> 

Ihre Aktionen wie folgt:

[HttpPost]
[MultiButton(MatchFormKey="action", MatchFormValue="Cancel")]
public ActionResult Cancel()
{
    return Content("Cancel clicked");
}

[HttpPost]
[MultiButton(MatchFormKey = "action", MatchFormValue = "Create")]
public ActionResult Create(Person person)
{
    return Content("Create clicked");
} 

Und erstelle diese Klasse:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultiButtonAttribute : ActionNameSelectorAttribute
{
    public string MatchFormKey { get; set; }
    public string MatchFormValue { get; set; }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        return controllerContext.HttpContext.Request[MatchFormKey] != null &&
            controllerContext.HttpContext.Request[MatchFormKey] == MatchFormValue;
    }
}
Owen
quelle
1
Fassen Sie immer am besten einen Link zusammen, auf den verwiesen wird (für den Tag, an dem der Blog verschwindet). Zusammenfassend lässt sich sagen, dass in diesem Blog ein MultiButtonAttributebenutzerdefiniertes Attribut empfohlen wird, um zwischen den Schaltflächen zum Senden zu unterscheiden. Eigentlich eine ganz schöne Idee.
Gone Coding
1
Und wenn Sie Arnis L.den gleichen Rat befolgt hätten, hätten Sie vielleicht bemerkt, dass er 4 Jahre zuvor genau den gleichen Link bereitgestellt hat:>
Gone Coding
3
// Buttons
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

// Controller
[HttpPost]
public ActionResult index(FormCollection collection)
{
    string submitType = "unknown";

    if(collection["submit"] != null)
    {
        submitType = "submit";
    }
    else if (collection["process"] != null)
    {
        submitType = "process";
    }

} // End of the index method
Fredrik Stigsson
quelle
Dies ist eine überlegene Lösung für alles andere, da sehr komplexe Formulardaten ohne benutzerdefinierte Parametersätze in jeder Aktion konsistent übergeben werden können, sodass die Steuerungslogik für komplexe Formulare in hohem Maße anpassbar ist. Kudos Fredrik :) Ich gehe davon aus, dass diese FormCollection in mehreren Formen übergeben wird?
Stokely
Vielen Dank Stokely. Sie können diese Methode aus mehreren Formularen aufrufen. Wenn Sie einen Ajax-Aufruf ausführen, können Sie viele Formulare in dieselbe FormCollection aufnehmen.
Fredrik Stigsson
3

Um es einfacher zu machen, werde ich sagen, dass Sie Ihre Schaltflächen wie folgt ändern können:

<input name="btnSubmit" type="submit" value="Save" />
<input name="btnProcess" type="submit" value="Process" />

Ihr Controller:

public ActionResult Create(string btnSubmit, string btnProcess)
{
    if(btnSubmit != null)
       // do something for the Button btnSubmit
    else 
       // do something for the Button btnProcess
}
Zonke-Bonke S'cekeleshe Msibi
quelle
2

Dieser Beitrag wird Coppermill nicht beantworten, da er vor langer Zeit beantwortet wurde. Mein Beitrag ist hilfreich für diejenigen, die nach einer solchen Lösung suchen. Zunächst muss ich sagen, dass "WDuffys Lösung völlig korrekt ist" und gut funktioniert, aber meine Lösung (nicht meine) wird in anderen Elementen verwendet und macht die Präsentationsschicht unabhängiger vom Controller (da Ihr Controller davon abhängt "Wert", der zum Anzeigen der Beschriftung der Schaltfläche verwendet wird. Diese Funktion ist für andere Sprachen wichtig.).

Hier ist meine Lösung, gib ihnen verschiedene Namen:

<input type="submit" name="buttonSave" value="Save"/>
<input type="submit" name="buttonProcess" value="Process"/>
<input type="submit" name="buttonCancel" value="Cancel"/>

Und Sie müssen die Namen der Schaltflächen als Argumente in der folgenden Aktion angeben:

public ActionResult Register(string buttonSave, string buttonProcess, string buttonCancel)
{
    if (buttonSave!= null)
    {
        //save is pressed
    }
    if (buttonProcess!= null)
    {
        //Process is pressed
    }
    if (buttonCancel!= null)
    {
        //Cancel is pressed
    }
}

Wenn der Benutzer die Seite mit einer der Schaltflächen sendet, hat nur eines der Argumente einen Wert. Ich denke, das wird für andere hilfreich sein.

Aktualisieren

Diese Antwort ist ziemlich alt und ich überdenke meine Meinung tatsächlich. Vielleicht ist die obige Lösung gut für Situationen, in denen Parameter an die Eigenschaften des Modells übergeben werden. Machen Sie sich keine Sorgen und finden Sie die beste Lösung für Ihr Projekt.

AAAA
quelle
Einige konstruktive Kritikpunkte: Dies wird durch die vorhandenen Antworten zum Zeitpunkt Ihrer Veröffentlichung gut abgedeckt. Außerdem lässt sich dies nicht gut skalieren. HTML gibt nur den input[type=submit]Wert zurück, der ausgelöst wurde, sodass alle Modelle an eine Eigenschaft mit derselben name(z. B. action) gebunden werden können . Anschließend können Sie Schaltflächen anhand der valueZeichenfolge unterscheiden, ohne dass so viele Variablen in Ihre Signatur eingefügt werden müssen . Bitte nehmen Sie sich auch etwas Zeit, um vor dem Posten über Formatierung / Einrückung nachzudenken.
KyleMit
0

Können Sie es mit Request.Form Collection nicht herausfinden? Wenn auf Prozess geklickt wird, ist das Anfrageformular ["Prozess"] nicht leer

chugh97
quelle
0

Geben Sie beiden Schaltflächen den Namen und überprüfen Sie den Wert aus dem Formular.

<div>
   <input name="submitButton" type="submit" value="Register" />
</div>

<div>
   <input name="cancelButton" type="submit" value="Cancel" />
</div>

Auf der Controllerseite:

public ActionResult Save(FormCollection form)
{
 if (this.httpContext.Request.Form["cancelButton"] !=null)
 {
   // return to the action;
 }

else if(this.httpContext.Request.Form["submitButton"] !=null)
 {
   // save the oprtation and retrun to the action;
 }
}
Aniket Sharma
quelle
0

In Core 2.2 Razor-Seiten funktioniert diese Syntax:

    <button type="submit" name="Submit">Save</button>
    <button type="submit" name="Cancel">Cancel</button>
public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
        return Page();
    var sub = Request.Form["Submit"];
    var can = Request.Form["Cancel"];
    if (sub.Count > 0)
       {
       .......
Leftware
quelle
Es könnte funktionieren, aber ich bevorzuge Parameter string submitgegenüber dem Schreiben string submit = Request.Form["Submit"];. Einer der größten Vorteile von Razor Pages und / oder MVC ist die Lesbarkeit der Methoden, andernfalls könnte es sich um PHP handeln.
Yzorg