Как получить значения формы из 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
Иногда вам нужны уродливые вещи, хорошо иметь выбор, когда вы уже знаете, каковы лучшие практики,
Оскар Ортис,
Почему кто-то все еще изучает точечную сеть, почему второй способ уродливее?
Goose
3
@ Гусь, потому что это волшебные струны. Вы не получаете никакой безопасности во время компиляции. Ваш код завершится ошибкой во время выполнения, если вы сделаете опечатку в имени переменной, тогда как если вы используете строгую типизацию, компилятор будет вашим другом.
Дарин Димитров
@DarinDimitrov имеет смысл. Не тот мир, из которого я родом. Очень приятная особенность.
Goose
104

Просто вы можете использовать FormCollectionкак:

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

Вы также можете использовать класс, который отображается со значениями формы, и механизм asp.net mvc автоматически заполняет его:

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

[HttpPost]
public ActionResult SubmitAction(MyForm form)
{      
  string var1 = form1.Var1;
}
Adeel
источник
Мне
36

Ответы очень хорошие, но в последней версии MVC и .NET есть еще один способ, который мне очень нравится использовать вместо ключей FormCollection и Request "старой школы".


Рассмотрим фрагмент 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?" />

Ваш контроллер фактически проанализирует данные формы и попытается доставить их вам как параметры определенного типа. Я включил флажок, потому что он сложный. Он возвращает текст «on», если отмечен, и null, если не отмечен. Однако требование состоит в том, что эти определенные переменные ДОЛЖНЫ существовать (если не допускают значения NULL (помните, что stringэто допускает значение NULL)), в противном случае возврат 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 Engine) перехватит переменную формы «variableName» (имя как вам нравится, но сохраняйте его согласованность) и попытается создать ее и преобразовать в 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 и вызывать ToList()

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

Рекомендуется использовать одну модель или ViewModel (модель, содержащую другие модели для создания сложной модели View) для каждой страницы. Предлагаемое смешивание и сопоставление может считаться плохой практикой, но пока оно работает и читается, это НЕ ПЛОХО. Однако он демонстрирует мощность и гибкость движка 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]);
}
A-Sharabiani
источник
2
Предупреждение, что это может быть плохой тоном (каламбур), но иногда вам просто нужны значения формы, и вы не можете полностью изменить подпись функции. Это единственное решение, подходящее для моей конкретной ситуации.
Ryan
Как провести модульное тестирование этого метода с помощью этих статических ссылок? FormCollection была бы более желательной, когда дело доходит до тестирования.
Kees de Wit
@KeesdeWit, если вы прочитали предыдущий комментарий, это не лучший способ, но иногда его используют как обходной путь. Для модульного тестирования, вероятно, вы можете смоделировать Requestи внедрить его в метод.
А-Шарабиани