Form değerleri HTTPPOST, sözlük veya?


112

Bu Eylem Yöntemine sahip bir MVC denetleyicim var:

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

Form, basit bir metin kutusu olan önemsiz bir formdur.

Soru

Parametre değerlerine nasıl erişirim?

Bir Görünümden gönderi yayınlamıyorum, gönderi harici olarak geliyor. Erişimim olan bir anahtar / değer çiftleri koleksiyonu olduğunu varsayıyorum.

Denedim Request.Params.Get("simpleTextBox");ama "Üzgünüz, isteğiniz işlenirken bir hata oluştu." Hatasını döndürüyor.

Yanıtlar:


155

Denetleyici eyleminizin form giriş adlarını yansıtan bir nesneyi almasını sağlayabilirsiniz ve varsayılan model bağlayıcı bu nesneyi sizin için otomatik olarak oluşturur:

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

    ... return something ...
}

Başka (açıkça daha çirkin) bir yol şudur:

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

    ... return something ...
}

5
Seçenek 2'deki derleyicinin yedeğini kaybettiğinizi belirtmek isterim. Model değişirse, derleyici ilgili denetleyicilerdeki değişikliği yakalayamaz. 2. seçenek için iyi durumlar var, ancak geniş kullanımı teşvik etmem.
Serguei Fedorov

1
Bazen Çirkin şeylere ihtiyaç duyarsınız, en iyi uygulamaların ne olduğunu zaten bildiğinizde bir seçim yapmanız iyidir
Oscar Ortiz

Hala nokta net öğrenen biri olarak, neden ikinci yol daha çirkin?
Kaz

3
@ Goose, çünkü sihirli dizeler. Herhangi bir derleme zamanı güvenliği elde edemezsiniz. Değişken adına bir yazım hatası yaparsanız, kodunuz çalışma zamanında başarısız olur, oysa güçlü yazım kullanıyorsanız, derleyici arkadaşınız olacaktır.
Darin Dimitrov

@DarinDimitrov mantıklı. Geldiğim dünyadan farklı. Çok güzel bir özellik.
Goose

104

Basitçe, aşağıdaki FormCollectiongibi kullanabilirsiniz :

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

Ayrıca Form değerleriyle eşlenmiş bir sınıf da kullanabilirsiniz ve asp.net mvc motoru bunu otomatik olarak doldurur:

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

[HttpPost]
public ActionResult SubmitAction(MyForm form)
{      
  string var1 = form1.Var1;
}

sınıf çözümünün kolay ve basit olmasını beğendim
Basheer AL-MOMANI

36

Cevaplar çok iyi ama MVC ve .NET'in son sürümünde "eski okul" FormCollection ve Request anahtarları yerine kullanmayı gerçekten sevdiğim başka bir yol var.


AJAX veya FORM POST'u yapan bir form etiketinde bulunan bir HTML pasajını düşünün.

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

Denetleyiciniz aslında form verilerini ayrıştıracak ve size tanımlı tipin parametreleri olarak teslim etmeye çalışacaktır. Yanıltıcı olduğu için onay kutusunu ekledim. İşaretliyse "açık" ve işaretlenmemişse null döndürür. Gerçi gereksinim, bu tanımlanmış değişkenlerin var olması ZORUNLUDUR (null yapılamazsa ( stringbunun null yapılabilir olduğunu unutmayın ), aksi takdirde AJAX veya POST geri başarısız olur.

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

Ayrıca herhangi bir jilet yardımcısı kullanmadan bir modeli geri gönderebilirsiniz. Bazen buna ihtiyaç duyulduğunu gördüm.

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

HTML işaretlemesi basitçe ...

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

ve denetleyiciniz (Razor Engine) Form Değişkeni "değişkenAdı" nı keser (ad istediğiniz gibi olur ancak tutarlı olmasını sağlar) ve onu oluşturmaya ve MyModel'e atmaya çalışır.

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

Bir denetleyici bir Model beklerken (bu durumda HomeModel), ayrıştırıcı onları varsayılan olarak, genellikle NULL olarak bırakacağından, TÜM alanları tanımlamanız gerekmez. İşin güzel yanı, Mark-up'ta çeşitli modelleri karıştırıp eşleştirebilmeniz ve geri ayrıştırma sonrası mümkün olduğunca doldurulacak olmasıdır. Sayfada bir model tanımlamanıza veya herhangi bir yardımcı kullanmanıza gerek yoktur.

İPUCU: Denetleyicideki parametrenin adı, HTML biçimlendirmesinde "name =" tanımlanan addır Model adı değil, ancak! İçindeki beklenen değişkenin adıdır!


Kullanımı List<>, biçimlendirmede biraz daha karmaşıktır.

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

<> Listesindeki Dizin her zaman sıfır tabanlı ve sıralı OLMALIDIR. 0,1,2,3.

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

Kullanma IEnumerable<>olmayan sıfır göre olan ve olmayan ardışık indeksleri geri göndermek. Bağlayıcıya yardımcı olmak için fazladan gizli bir girdi eklememiz gerekiyor.

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

Ve kodun sadece IEnumerable'ı kullanması ve ToList()

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

Sayfa başına tek bir Model veya bir ViewModel (karmaşık bir 'Görünüm' Modeli oluşturmak için diğer modelleri içeren Model) kullanılması önerilir. Önerilen şekilde karıştırma ve eşleştirme kötü uygulama olarak kabul edilebilir, ancak çalıştığı ve okunabilir olduğu sürece KÖTÜ değildir. Bununla birlikte, Razor motorunun gücünü ve esnekliğini gösterir.

Bu nedenle, rastgele bir şeyi bırakmanız veya bir Razor yardımcısından başka bir değeri geçersiz kılmanız gerekiyorsa veya sıradışı bazı veri kombinasyonlarını kullanan tek bir form için kendi yardımcılarınızı yapmak istemiyorsanız, bu yöntemleri hızlı bir şekilde kullanarak ekstra veri.


Dizin seçeneğinin kullanılması belirsizdir. Tanrı'nın yeşil dünyasında bunu kim bilebilirdi ya da var olduğunu ?! Ama bu yazıyı bulduğuma sevindim. Çok fazla ağ trafiği kurtaracak.
Michael Silver

1
Bu benim için çalıştı, ancak yalnızca <input type = "hidden" id = "myId"> öğesini @ Html.Hidden ("myId") olarak değiştirdikten sonra
radkan

@Piotr - lütfen MyModel ve MyHomes ile referans tutarsızlıklarınızı düzeltin. Şu anda nasıl olduğu kafa karışıklığına neden oluyor.
Spencer Sullivan

15

Form verilerini doğrudan Http isteğinden, herhangi bir model bağlaması olmadan almak istiyorsanız veya FormCollectionbunu kullanabilirsiniz:

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

2
Bunun kötü bir biçimde olabileceğine dikkat edin (kelime anlamı yoktur), ancak bazen yalnızca form değerlerini istersiniz ve işlev imzasını temiz bir şekilde değiştiremezsiniz. Benim özel durumuma uyan tek çözüm budur.
Ryan

Bu yöntem, bu statik referanslarla nasıl birim test edilir? FormCollection, test söz konusu olduğunda çok daha cazip olacaktır.
Kees de Wit

@KeesdeWit Eğer önceki yorumu okursanız bu en iyi yol değildir, ancak bazen geçici çözüm olarak kullanın. Birim testi için, muhtemelen alay edebilir Requestve yönteme enjekte edebilirsiniz .
A-Sharabiani
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.