Як отримати значення форм із HTTPPOST, словника чи?


112

У мене є контролер MVC, який має цей спосіб дії:

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

Форма - це нетривіальна форма з простим текстовим полем.

Питання

Як я отримую доступ до значень параметрів?

Я не публікую повідомлення з погляду, публікація надходить зовні. Я припускаю, що є колекція пар ключів / значень, до яких я маю доступ.

Я спробував, Request.Params.Get("simpleTextBox");але вона повертає помилку "Вибачте, сталася помилка під час обробки вашого запиту."

Відповіді:


155

Ви можете змусити ваш контролер діяти об'єктом, який відображатиме назви введення форми, а в'яжуча модель за замовчуванням автоматично створить цей об’єкт для вас:

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

    ... return something ...
}

Ще один (очевидно потворніший) спосіб:

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

    ... return something ...
}

5
Я просто хотів би зазначити, що ви втрачаєте резервну копію компілятора у варіанті 2. Якщо модель зміниться, компілятор не впізнає зміни у відповідних контролерах. Існують хороші випадки для варіанту 2, але я не рекомендую широко використовувати.
Сергей Федоров

1
Іноді вам потрібні некрасиві речі, добре мати вибір, коли ви вже знаєте, які найкращі практики
Оскар Ортіз

Коли хтось ще вивчає крапку, чому другий спосіб потворніший?
Гусак

3
@Goose, тому що це чарівні струни. Ви не отримуєте жодної безпеки часу компіляції. Ваш код не вдасться виконати, якщо ви введете помилку в назві змінної, тоді як якщо ви використовуєте сильний набір тексту, компілятор буде вашим другом.
Дарин Димитров

@DarinDimitrov має сенс. Інший, ніж світ, з якого я родом. Дуже приємна особливість.
Гусак

104

Просто ви можете використовувати FormCollection:

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

Ви також можете використовувати клас, який відображається зі значеннями Form, і двигун asp.net mvc автоматично заповнює його:

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

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

Мені сподобалося рішення класу, його легко і просто
Basheer AL-MOMANI

36

Відповіді дуже хороші, але є ще один спосіб у останньому випуску MVC та .NET, який мені дуже подобається використовувати замість клавіш FormCollection і Request "old school".


Розглянемо фрагмент HTML, який міститься у тезі форми, який або AJAX, або 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?" />

Ваш контролер фактично проаналізує дані форми та спробує доставити їх вам як параметри визначеного типу. Я включив прапорець, тому що це хитро. Він повертає текст "увімкнено", якщо він встановлений, і нуль, якщо не встановлений. Однак, вимога полягає в тому, що ці визначені змінні ОБОВ'ЯЗКОВО існують (якщо тільки нульові (пам’ятайте, хоча це stringє нульовими)), інакше назад AJAX або POST не вдасться.

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

Ви також можете опублікувати модель назад, не використовуючи жодної бритви. Я стикався, що це потрібно кілька разів.

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

Розмітка HTML просто буде ...

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

і ваш контролер (двигун Razor) перехопить змінну форми "variaName" (ім'я так, як вам подобається, але зберігайте її послідовно) і спробує створити її та передати в MyModel.

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

Коли контролер очікує Модель (в даному випадку HomeModel), вам не потрібно визначати ВСІ поля, оскільки аналізатор просто залишить їх за замовчуванням, як правило, NULL. Приємно те, що ти можеш змішувати та співставляти різні моделі на маркуванні, і синтаксичний синтаксичний аналіз буде заповнено максимально. Вам не потрібно визначати модель на сторінці або використовувати будь-які помічники.

ПОРАДА: Ім'я параметра в контролері - це ім'я, визначене в розмітці HTML "name =" не ім'я Моделі, а ім'я очікуваної змінної у!


Використання List<>трохи складніше в його розмітці.

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

Індекс у списку <> ОБОВ'ЯЗКОВО повинен бути нульовим та послідовним. 0,1,2,3.

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

Використання IEnumerable<>для нульових та не послідовних індексів опублікувати назад. Нам потрібно додати додатковий прихований вхід, щоб допомогти палітурці.

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

А код просто потребує використання IEnumerable та call ToList()

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

Рекомендується використовувати одну Модель або ViewModel (Модель, що містить інші моделі для створення складної моделі "Перегляд") на сторінку. Змішування та узгодження, як було запропоновано, можна вважати поганою практикою, але поки це працює і читається не БАД. Однак це демонструє потужність і гнучкість двигуна Razor.

Тож якщо вам потрібно вписати щось довільне або змінити інше значення від помічника Razor або просто не відчуваєте, як створювати власні помічники, для єдиної форми, яка використовує якусь незвичну комбінацію даних, ви можете швидко скористатися цими методами, щоб прийняти додаткові дані.


Використання параметра "Індекс" є малозрозумілим. Хто на Божій зеленій землі міг би знати, що він використовував те чи що воно взагалі існувало ?! Але я радий, що знайшов цю посаду. Це допоможе заощадити велику кількість мережевого трафіку.
Майкл Сільвер

1
Це працювало для мене, але лише після того, як я змінив <input type = "hidden" id = "myId"> на @ Html.Hidden ("myId")
radkan

@Piotr - виправте невідповідність своїх посилань з MyModel та MyHomes. Це викликає плутанину як зараз.
Спенсер Салліван

15

Якщо ви хочете отримати дані форми безпосередньо з Http-запиту, без будь-яких прив’язок моделі або FormCollectionви можете скористатися цим:

[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
Застережте, що це може бути погана форма (каламбур не призначений), але іноді ви просто хочете значення форми, і ви не можете чітко змінити підпис функції. Це єдине рішення, яке підходило моїй конкретній ситуації.
Райан

Як з'єднати тест цього методу з тими статичними посиланнями? FormCollection виявиться набагато бажанішим, коли мова йде про тестування.
Kees de Wit

@KeesdeWit якщо ви прочитали попередній коментар, це не найкращий спосіб, але іноді використовуйте його як спосіб вирішення. Для одиничного тестування, ймовірно, ви можете знущатися над Requestі вводити його методу.
A-Sharabiani
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.