Bagaimana cara mengambil nilai formulir dari HTTPPOST, kamus atau?

112

Saya memiliki pengontrol MVC yang memiliki Metode Tindakan ini:

[HttpPost]
public ActionResult SubmitAction()
{
     // Get Post Params Here
 ... return something ...
}

Formulir tersebut merupakan formulir non-sepele dengan kotak teks sederhana.

Pertanyaan

Bagaimana saya mengakses nilai parameter?

Saya tidak memposting dari View, postingan datang dari luar. Saya berasumsi bahwa ada kumpulan pasangan kunci / nilai yang dapat saya akses.

Saya mencoba Request.Params.Get("simpleTextBox");tetapi mengembalikan kesalahan "Maaf, terjadi kesalahan saat memproses permintaan Anda.".

Richard
sumber

Jawaban:

155

Anda dapat meminta tindakan pengontrol Anda mengambil objek yang akan mencerminkan nama input formulir dan pengikat model default akan secara otomatis membuat objek ini untuk Anda:

[HttpPost]
public ActionResult SubmitAction(SomeModel model)
{
    var value1 = model.SimpleProp1;
    var value2 = model.SimpleProp2;
    var value3 = model.ComplexProp1.SimpleProp1;
    ...

    ... return something ...
}

Cara lain (jelas lebih buruk) adalah:

[HttpPost]
public ActionResult SubmitAction()
{
    var value1 = Request["SimpleProp1"];
    var value2 = Request["SimpleProp2"];
    var value3 = Request["ComplexProp1.SimpleProp1"];
    ...

    ... return something ...
}
Darin Dimitrov
sumber
5
Saya hanya ingin menunjukkan bahwa Anda kehilangan cadangan kompiler di opsi 2. Jika model berubah, kompiler tidak akan menangkap perubahan dalam pengontrol terkait. Ada kasus yang bagus untuk opsi 2 tetapi saya tidak akan mendorong penggunaan yang luas.
Serguei Fedorov
1
Kadang-kadang Anda membutuhkan barang-barang Jelek, baik jika Anda memiliki pilihan ketika Anda sudah tahu apa praktik terbaik
Oscar Ortiz
Sebagai seseorang yang masih belajar dot net, mengapa cara kedua lebih jelek?
Angsa
3
@ Angsa, karena itu adalah benang ajaib. Anda tidak mendapatkan keamanan waktu kompilasi. Kode Anda akan gagal saat runtime jika Anda membuat kesalahan ketik pada nama variabel sedangkan jika Anda menggunakan pengetikan yang kuat, kompiler akan menjadi teman Anda.
Darin Dimitrov
@Darinrov masuk akal. Berbeda dari dunia asalku. Fitur yang sangat bagus.
Angsa
104

Sederhananya, Anda dapat menggunakan FormCollectionseperti:

[HttpPost] 
public ActionResult SubmitAction(FormCollection collection)
{
     // Get Post Params Here
 string var1 = collection["var1"];
}

Anda juga dapat menggunakan kelas, yang dipetakan dengan nilai Formulir, dan mesin mvc asp.net secara otomatis mengisinya:

//Defined in another file
class MyForm
{
  public string var1 { get; set; }
}

[HttpPost]
public ActionResult SubmitAction(MyForm form)
{      
  string var1 = form1.Var1;
}
Adeel
sumber
Saya menyukai solusi kelas yang mudah dan sederhana
Basheer AL-MOMANI
36

Jawabannya sangat bagus tetapi ada cara lain dalam rilis terbaru MVC dan .NET yang sangat saya suka gunakan, daripada menggunakan kunci FormCollection dan Request "jadul".


Pertimbangkan potongan HTML yang terdapat dalam tag formulir yang melakukan AJAX atau FORM POST.

<input type="hidden"   name="TrackingID" 
<input type="text"     name="FirstName"  id="firstnametext" />
<input type="checkbox" name="IsLegal"  value="Do you accept terms and conditions?" />

Kontroler Anda akan benar-benar mengurai data formulir dan mencoba mengirimkannya kepada Anda sebagai parameter dari tipe yang ditentukan. Saya menyertakan kotak centang karena ini rumit. Ia mengembalikan teks "on" jika dicentang dan null jika tidak dicentang. Namun persyaratannya adalah bahwa variabel yang ditentukan ini HARUS ada (kecuali nullable (ingat meskipun itu stringnullable)) jika tidak AJAX atau POST back akan gagal.

[HttpPost]
public ActionResult PostBack(int TrackingID, string FirstName, string IsLegal){
    MyData.SaveRequest(TrackingID,FirstName, IsLegal == null ? false : true);
}

Anda juga dapat memposting kembali model tanpa menggunakan pisau cukur. Saya telah menemukan bahwa ini diperlukan beberapa kali.

public Class HomeModel
{
  public int HouseNumber { get; set; }
  public string StreetAddress { get; set; }
}

Markup HTML hanya akan ...

<input type="text" name="variableName.HouseNumber" id="whateverid" >

dan controller Anda (Razor Engine) akan mencegat Variabel Formulir "variableName" (nama sesuka Anda tetapi tetap konsisten) dan mencoba membangunnya dan memasukkannya ke MyModel.

[HttpPost]
public ActionResult PostBack(HomeModel variableName){
    postBack.HouseNumber; //The value user entered
    postBack.StreetAddress; //the default value of NULL.
}

Ketika controller mengharapkan sebuah Model (dalam hal ini HomeModel) Anda tidak perlu mendefinisikan SEMUA field karena parser akan membiarkannya di default, biasanya NULL. Hal yang menyenangkan adalah Anda dapat mencampur dan mencocokkan berbagai model di Mark-up dan parse posting kembali akan terisi sebanyak mungkin. Anda tidak perlu menentukan model di halaman atau menggunakan pembantu apa pun.

TIPS: Nama parameter dalam pengontrol adalah nama yang ditentukan dalam mark-up HTML "name =" bukan nama Model, tetapi nama variabel yang diharapkan di!


Penggunaannya List<>sedikit lebih rumit dalam mark-upnya.

<input type="text" name="variableNameHere[0].HouseNumber" id="id"           value="0">
<input type="text" name="variableNameHere[1].HouseNumber" id="whateverid-x" value="1">
<input type="text" name="variableNameHere[2].HouseNumber"                   value="2">
<input type="text" name="variableNameHere[3].HouseNumber" id="whateverid22" value="3">

Indeks pada Daftar <> HARUS selalu berbasis nol dan berurutan. 0,1,2,3.

[HttpPost]
public ActionResult PostBack(List<HomeModel> variableNameHere){
     int counter = MyHomes.Count()
     foreach(var home in MyHomes)
     { ... }
}

Menggunakan IEnumerable<>untuk indeks berbasis non-nol dan non-sekuensial memposting kembali. Kami perlu menambahkan masukan tersembunyi ekstra untuk membantu pengikat.

<input type="hidden" name="variableNameHere.Index" value="278">
<input type="text" name="variableNameHere[278].HouseNumber" id="id"      value="3">

<input type="hidden" name="variableNameHere.Index" value="99976">
<input type="text" name="variableNameHere[99976].HouseNumber" id="id3"   value="4">

<input type="hidden" name="variableNameHere.Index" value="777">
<input type="text" name="variableNameHere[777].HouseNumber" id="id23"    value="5">

Dan kodenya hanya perlu menggunakan IEnumerable dan memanggil ToList()

[HttpPost]
public ActionResult PostBack(IEnumerable<MyModel> variableNameHere){
     int counter = variableNameHere.ToList().Count()
     foreach(var home in variableNameHere)
     { ... }
}

Disarankan untuk menggunakan Model tunggal atau ViewModel (Model yang mengekang model lain untuk membuat Model 'Tampilan' yang kompleks) per halaman. Mencampur dan mencocokkan seperti yang diusulkan dapat dianggap praktik yang buruk, tetapi selama berhasil dan dapat dibaca tidak BURUK. Bagaimanapun, itu menunjukkan kekuatan dan fleksibilitas mesin Razor.

Jadi jika Anda perlu memasukkan sesuatu yang sewenang-wenang atau mengganti nilai lain dari helper Razor, atau tidak ingin membuat pembantu Anda sendiri, untuk satu formulir yang menggunakan beberapa kombinasi data yang tidak biasa, Anda dapat dengan cepat menggunakan metode ini untuk menerima tambahan data.

Piotr Kula
sumber
Menggunakan opsi Indeks tidak jelas. Siapa di bumi hijau Tuhan yang tahu menggunakan itu atau bahkan ada ?! Tapi, saya senang saya menemukan posting ini. Ini akan menghemat banyak lalu lintas jaringan.
Michael Silver
1
Ini berhasil untuk saya, tetapi hanya setelah saya mengubah <input type = "hidden" id = "myId"> menjadi @ Html.Hidden ("myId")
radkan
@Piotr - perbaiki inkonsistensi referensi Anda dengan MyModel dan MyHomes. Ini menyebabkan kebingungan bagaimana keadaannya saat ini.
Spencer Sullivan
15

Jika Anda ingin mendapatkan data formulir langsung dari permintaan Http, tanpa ikatan model apa pun atau FormCollectionAnda dapat menggunakan ini:

[HttpPost] 
public ActionResult SubmitAction() {

    // This will return an string array of all keys in the form.
    // NOTE: you specify the keys in form by the name attributes e.g:
    // <input name="this is the key" value="some value" type="test" />
    var keys = Request.Form.AllKeys;

    // This will return the value for the keys.
    var value1 = Request.Form.Get(keys[0]);
    var value2 = Request.Form.Get(keys[1]);
}
A-Sharabiani
sumber
2
Perhatian bahwa ini mungkin bentuk yang buruk (tidak ada permainan kata-kata) tetapi terkadang Anda hanya menginginkan nilai formulir dan Anda tidak dapat mengubah tanda tangan fungsi dengan rapi. Ini adalah satu-satunya solusi di sini yang sesuai dengan situasi khusus saya.
Ryan
Bagaimana cara menguji unit metode ini dengan referensi statis tersebut? FormCollection akan jauh lebih diinginkan dalam hal pengujian.
Kees de Wit
@KeesdeWit jika Anda membaca komentar sebelumnya, ini bukan cara terbaik, tetapi terkadang digunakan sebagai solusi. Untuk pengujian unit, mungkin Anda bisa mengejek Requestdan menyuntikkannya ke metode.
A-Sharabiani