MVC quale pulsante di invio è stato premuto


128

Ho due pulsanti sul mio modulo MVC:

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

Dall'azione del mio controller come faccio a sapere quale è stato premuto?


Perché non aggiungere semplicemente eventi onclick a questi pulsanti che vanno alla loro chiamata AJAX che andranno ai loro metodi appropriati? cioè <input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" />:?
ragerory

Risposte:


169

Assegna allo stesso modo entrambi i pulsanti di invio

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

Quindi nel controller ottieni il valore di submit. Solo il pulsante selezionato passerà il suo valore.

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

Ovviamente puoi valutare quel valore per eseguire diverse operazioni con un blocco switch.

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

    return View();
}

13
Fai attenzione ai problemi che la localizzazione potrebbe portare a questa soluzione, alla quale la soluzione di Darin non è suscettibile.
Richard Szalay,

Due input con lo stesso nome comportano la registrazione di un array con un elemento per ciascun valore, non un singolo valore come implicito. Quindi vorrei poter dire diversamente poiché speravo / cercavo di usarlo, ma questo non funziona.
Christopher King,

1
@RichardSzalay - non potresti semplicemente usarlo <button type="submit" name="action" value="draft"> Internationalized Save Text </button>per scopi i18n, quindi l'utente che affronta la stringa è personalizzabile, e i nomi degli elementi del modulo non sono mai direttamente esposti all'utente (che è strano in sé e per sé)
KyleMit

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

E nell'azione del controller:

public ActionResult SomeAction(string submit)
{
    if (!string.IsNullOrEmpty(submit))
    {
        // Save was pressed
    }
    else
    {
        // Process was pressed
    }
}

1
Immagino che più pulsanti possano essere aggiunti semplicemente aggiungendolo all'elenco dei parametri e nominandolo correttamente. Bella soluzione!
GONeale,

35

questa è una risposta migliore, quindi possiamo avere sia testo che valore per un pulsante:

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>

e il controller:

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

in breve è un pulsante INVIA ma tu scegli il nome usando l'attributo name, è ancora più potente perché non sei obbligato a inviare il nome o il pulsante nei parametri del metodo del controller, puoi chiamarlo come preferisci ...


Grazie signore, questo è esattamente ciò di cui ho bisogno
oHoodie,

Ciò si interrompe se si dispone di un sistema multilingue che modifica il valore del pulsante in base alla lingua.
Dave Tapson,

Dave - Non credo che qualcuno codificherebbe un sistema del genere. È come localizzare i nomi dei controller o delle funzioni. Il valore del pulsante è solo per uso lato server: non viene visualizzato da nessuna parte e non deve essere localizzato.
NickG

20

puoi identificare il tuo pulsante da lì tag nome come di seguito, è necessario controllare in questo modo nel controller

if (Request.Form["submit"] != null)
{
//Write your code here
}
else if (Request.Form["process"] != null)
{
//Write your code here
}

questo è molto utile in situazioni in cui non si desidera passare il nome del pulsante al messaggio post action.
Yogihosting

in questo scenario può essere più complicato deridere la classe Request nel test unitario.
Muflix,

6

Ecco un modo davvero carino e semplice per farlo con istruzioni davvero facili da seguire usando un MultiButtonAttribute personalizzato:

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

Per riassumere, fai i pulsanti di invio in questo modo:

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

Le tue azioni in questo modo:

[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");
} 

E crea questa classe:

[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;
    }
}

1
Sempre meglio riassumere un link di riferimento (per il giorno in cui il blog svanisce). In sintesi, il blog sostiene di avere un MultiButtonAttributeattributo personalizzato per consentire la differenziazione tra i pulsanti di invio. In realtà una bella idea.
Codice finito

1
E se Arnis L.avesse seguito lo stesso consiglio, potresti aver notato che aveva fornito lo stesso identico link 4 anni prima:>
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

Questa è una soluzione superiore a tutto il resto pubblicato in quanto consente il passaggio coerente di dati di moduli molto complessi senza set di parametri personalizzati in ogni azione, consentendo alla logica del controller di essere altamente personalizzabile per i moduli complessi. Complimenti Fredrik :) Suppongo che questo FormCollection passerà in più forme?
Stokely,

Grazie Stokely. È possibile chiamare questo metodo da più moduli, se si effettua una chiamata ajax, è possibile includere molti moduli nello stesso FormCollection.
Fredrik Stigsson,

3

Per semplificare, dirò che è possibile modificare i pulsanti come segue:

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

Il tuo controller:

public ActionResult Create(string btnSubmit, string btnProcess)
{
    if(btnSubmit != null)
       // do something for the Button btnSubmit
    else 
       // do something for the Button btnProcess
}

2

Questo post non risponderà a Coppermill, perché gli è stato risposto molto tempo fa. Il mio post sarà utile per chi cercherà una soluzione come questa. Prima di tutto, devo dire "La soluzione di WDuffy è totalmente corretta" e funziona benissimo, ma la mia soluzione (non proprio la mia) verrà utilizzata in altri elementi e rende il livello di presentazione più indipendente dal controller (perché il controller dipende da "valore" che viene utilizzato per mostrare l'etichetta del pulsante, questa funzione è importante per altre lingue.).

Ecco la mia soluzione, dai loro nomi diversi:

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

E devi specificare i nomi dei pulsanti come argomenti nell'azione come sotto:

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
    }
}

quando l'utente invia la pagina utilizzando uno dei pulsanti, solo uno degli argomenti avrà valore. Immagino che questo sarà utile per gli altri.

Aggiornare

Questa risposta è piuttosto vecchia e in realtà riconsidero la mia opinione. forse sopra la soluzione è buona per la situazione che passa il parametro alle proprietà del modello. non preoccuparti e prendi la migliore soluzione per il tuo progetto.


Alcune critiche costruttive insieme: questo è ben coperto dalle risposte esistenti al momento della tua pubblicazione. Inoltre, questo non si adatta bene. L'HTML riporterà solo il input[type=submit]valore che è stato attivato, in modo che tutti i modelli possano essere associati a una proprietà con lo stesso name(es. action) E quindi è possibile differenziare i pulsanti in base a valuequella stringa senza la necessità di introdurre tante variabili nella firma . Ti preghiamo inoltre di dedicare un po 'di tempo a pensare alla formattazione / rientro prima di pubblicare.
KyleMit

0

Non riesci a scoprirlo utilizzando Request.Form Collection? Se si fa clic su process, request.form ["process"] non sarà vuoto


0

Assegna il nome a entrambi i pulsanti e ottieni il segno di spunta dal valore.

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

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

Sul lato controller:

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;
 }
}

0

Nelle pagine Core 2.2 Razor questa sintassi funziona:

    <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)
       {
       .......

Potrebbe funzionare, ma preferisco il parametro alla string submitscrittura string submit = Request.Form["Submit"];. Uno dei maggiori vantaggi di Razor Pages e / o MVC è la leggibilità dei metodi, altrimenti potrebbe essere PHP.
yzorg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.