MVC yang mengirimkan tombol telah ditekan

128

Saya memiliki dua tombol di formulir MVC saya:

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

Dari tindakan Kontroler saya, bagaimana saya tahu yang mana yang telah ditekan?

Coppermill
sumber
Mengapa tidak menambahkan acara onclick ke tombol-tombol ini yang pergi ke panggilan AJAX mereka sendiri yang akan pergi ke metode yang sesuai? yaitu: <input name="submit" type="submit" id="submit" value="Save" onclick="saveMethod" />?
ragerory

Jawaban:

169

Beri nama kedua tombol kirim Anda sama

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

Kemudian di controller Anda dapatkan nilai submit. Hanya tombol yang diklik yang akan melewati nilainya.

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

Tentu saja Anda dapat menilai nilai itu untuk melakukan operasi yang berbeda dengan blok sakelar.

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
sumber
13
Hati-hati dengan masalah yang bisa diakibatkan oleh pelokalan terhadap solusi ini, yang mana solusi Darwin tidak rentan.
Richard Szalay
Dua input dengan nama yang sama menghasilkan array yang diposting dengan satu elemen untuk setiap nilai, bukan nilai tunggal seperti yang tersirat. Jadi saya berharap saya bisa mengatakan sebaliknya karena saya berharap / mencoba menggunakan ini, tetapi ini tidak berhasil.
Christopher King
1
@RichardSzalay - tidak bisakah Anda hanya menggunakan <button type="submit" name="action" value="draft"> Internationalized Save Text </button>untuk tujuan i18n, sehingga string yang menghadap pengguna dapat disesuaikan, dan nama elemen bentuk tidak pernah langsung terpapar ke pengguna (yang aneh dengan sendirinya)
KyleMit
48
<input name="submit" type="submit" id="submit" value="Save" />
<input name="process" type="submit" id="process" value="Process" />

Dan dalam aksi pengontrol Anda:

public ActionResult SomeAction(string submit)
{
    if (!string.IsNullOrEmpty(submit))
    {
        // Save was pressed
    }
    else
    {
        // Process was pressed
    }
}
Darin Dimitrov
sumber
1
Saya membayangkan lebih banyak tombol dapat ditambahkan dengan hanya menambahkannya ke daftar parameter dan memberi nama dengan benar. Solusi bagus!
GONeale
35

ini adalah jawaban yang lebih baik, sehingga kami dapat memiliki teks dan nilai untuk sebuah tombol:

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>

dan pengontrol:

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

singkatnya itu adalah tombol PENGIRIM tetapi Anda memilih nama menggunakan atribut nama, itu bahkan lebih kuat karena Anda tidak berkewajiban untuk mengirimkan nama atau tombol dalam parameter metode pengontrol, Anda dapat memanggilnya sesuka Anda ...

Yakir Manor
sumber
Terima kasih Pak, ini persis apa yang saya butuhkan
oHoodie
Ini rusak jika Anda memiliki sistem multibahasa yang mengubah nilai tombol sesuai dengan bahasa.
Dave Tapson
Dave - Saya tidak berpikir ada orang yang akan mengkode sistem seperti itu. Itu seperti melokalkan nama pengontrol atau nama fungsi Anda. The nilai dari tombol untuk penggunaan sisi server hanya - tidak menampilkan di mana saja dan tidak perlu dilokalisasi.
NickG
20

Anda dapat mengidentifikasi tombol Anda dari sana tag nama seperti di bawah ini, Anda perlu memeriksa seperti ini di controller Anda

if (Request.Form["submit"] != null)
{
//Write your code here
}
else if (Request.Form["process"] != null)
{
//Write your code here
}
Kinjal Gohil
sumber
ini sangat membantu dalam situasi ketika Anda tidak ingin meneruskan nama tombol ke post actionresult.
yogihosting
dalam skenario ini akan lebih sulit untuk mengejek kelas Permintaan dalam unit test.
Muflix
6

Berikut cara yang sangat bagus dan sederhana untuk melakukannya dengan sangat mudah untuk mengikuti instruksi menggunakan MultiButtonAttribute khusus:

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

Untuk meringkas, buat tombol kirim Anda seperti ini:

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

Tindakan Anda seperti ini:

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

Dan buat kelas ini:

[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
sumber
1
Selalu yang terbaik untuk meringkas tautan yang dirujuk (untuk hari blog itu hilang). Singkatnya, pendukung blog memiliki MultiButtonAttributeatribut khusus untuk memungkinkan membedakan antara tombol kirim. Sebenarnya ide yang cukup bagus.
Hilang Coding
1
Dan jika Arnis L.mengikuti saran yang sama, Anda mungkin memperhatikan bahwa dia memberikan tautan yang sama persis 4 tahun sebelumnya:>
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
sumber
Ini adalah solusi unggul untuk semua yang diposting karena memungkinkan data formulir yang sangat kompleks untuk diteruskan secara konsisten tanpa set parameter yang disesuaikan di setiap tindakan, yang memungkinkan logika pengontrol sangat dapat disesuaikan untuk bentuk kompleks. Kudos Fredrik :) Saya menganggap FormCollection ini akan lulus dalam berbagai bentuk?
Stokely
Terima kasih Stokely. Anda bisa memanggil metode ini dari beberapa formulir, jika Anda melakukan panggilan ajax maka Anda bisa memasukkan banyak formulir dalam FormCollection yang sama.
Fredrik Stigsson
3

Untuk membuatnya lebih mudah, saya akan mengatakan Anda dapat mengubah tombol Anda sebagai berikut:

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

Pengontrol Anda:

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
sumber
2

Posting ini tidak akan menjawab ke Coppermill, karena dia sudah dijawab lama. Posting saya akan sangat membantu bagi yang akan mencari solusi seperti ini. Pertama-tama, saya harus mengatakan "solusi WDuffy benar-benar benar" dan berfungsi dengan baik, tetapi solusi saya (tidak benar-benar milik saya) akan digunakan dalam elemen lain dan itu membuat lapisan presentasi lebih independen dari pengontrol (karena pengontrol Anda bergantung pada "nilai" yang digunakan untuk menampilkan label tombol, fitur ini penting untuk bahasa lain.).

Ini solusi saya, beri mereka nama yang berbeda:

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

Dan Anda harus menentukan nama tombol sebagai argumen dalam tindakan seperti di bawah ini:

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

ketika pengguna mengirimkan halaman menggunakan salah satu tombol, hanya salah satu argumen yang akan memiliki nilai. Saya kira ini akan bermanfaat bagi orang lain.

Memperbarui

Jawaban ini cukup lama dan saya benar-benar mempertimbangkan kembali pendapat saya. mungkin solusi di atas baik untuk situasi yang melewatkan parameter ke properti model. jangan repot-repot sendiri dan mengambil solusi terbaik untuk proyek Anda.

AAAA
sumber
Beberapa kritik membangun: ini tercakup dengan baik oleh jawaban yang ada saat Anda memposting ini. Selain itu, ini tidak skala dengan baik. HTML hanya akan memposting kembali input[type=submit]nilai yang dipicu, sehingga mereka semua dapat memodelkan mengikat ke properti dengan yang sama name(mis. action) Dan kemudian Anda dapat membedakan tombol berdasarkan pada valuestring itu tanpa perlu memperkenalkan banyak variabel dalam tanda tangan Anda . Harap juga luangkan waktu untuk memikirkan tentang pemformatan / indentasi sebelum memposting.
KyleMit
0

Tidak bisakah Anda mencari tahu dengan menggunakan Request.Form Collection? Jika proses diklik, request.form ["proses"] tidak akan kosong

chugh97
sumber
0

Beri nama untuk kedua tombol dan Dapatkan centang nilai dari formulir.

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

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

Di sisi pengontrol:

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
sumber
0

Di halaman Core 2.2 Razor, sintaks ini berfungsi:

    <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
sumber
Mungkin berhasil, tapi saya lebih suka parameter string submitvs tulisan string submit = Request.Form["Submit"];. Salah satu manfaat terbesar Razor Pages dan / atau MVC adalah keterbacaan metode, jika tidak bisa berupa PHP.
yzorg