Прежде чем ответить на ваши вопросы, я не понимаю, что new {questResponses = Model[i] }))
делает в ваших формах:
using (Html.BeginForm("CheckQuestions", "Checks", FormMethod.Post, new {questResponses = Model[i] }))
{
...
}
Model[i]
- сложный объект. Все, что у вас было, это имя объекта:
Q1: If the Controller POST method has just a single parameter
Since you're using a for loop to generate each form and inputs within the form, the name of those inputs will be in the forms of [INDEX].NAME
:
By default, the model binding will bind those inputs (QuestionId, QuestionText and Response) to a matching object. QuestionResponseViewModel
indeed matches that. The problem is [INDEX].
prefix.
In order for the default model binding to work, the parameter name you declare in the POST method has to be called [INDEX]
, i.e., [0]
for the first form, [1]
for the second form and so on:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CheckQuestions(QuestionResponseVM [0])
{
...
}
Но вы знаете, что мы не можем объявить ничего подобного в C# .
Исправление для Q1
Вместо использования обычного для l oop, вы можете использовать foreach
для генерации каждой формы. Таким образом, вы избавляетесь от необходимости именовать параметр, который изменяется для каждой формы.
Еще один «GOTYOU» здесь заключается в том, что параметр в контроллере должен соответствовать переменной, которую вы объявлено в for l oop для каждого QuestionResponseViewModel
:
@foreach (var qrVM in Model)
{
using(Html.BeginForm("..."))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(x => qrVM.QuestionId)
<tr>
<td>
@Html.DisplayFor(x => qrVM.QuestionId)
@Html.HiddenFor(x => qrVM.QuestionId)
</td>
...
</tr>
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CheckQuestions(QuestionResponseVM qrVM)
{
// If you name the parameter something else, it won't bind!
...
}
Если вы думаете об этом, это имеет смысл, потому что вы знаете, что форма будет публиковать данные с такими ключами, как qrVM.QuestionId
, qrVM.QuestionText
обратно на сервер. Привязка модели по умолчанию будет искать модель, которая имеет эти свойства и называется qrVM
.
введите описание изображения здесь
Q2: изменить параметр на список
Когда первая форма отправляет обратно на сервер, данные формы в теле запроса будут выглядеть так:
[0].RequestionId: 1
[0].RequestionText: Question 1
[0].Response: xxx
MVC модель привязка по-прежнему достаточно умна и считает, что вы публикуете первый элемент объявленного вами списка. Следовательно, вы увидите, что List<QuestionResponseVM> questResponses
захватывает правильные данные для первой формы.
А как насчет второй и третьей формы? Если вы отправите данные, например, во вторую форму, данные формы в теле запроса будут выглядеть так:
[1].RequestionId: 2
[1].RequestionText: Question 2
[1].Response: xxx
MVC привязка модели видит его как второй элемент списка, но где 1-й элемент? И он запутался, поэтому не смог привязать данные к параметру. Следовательно, вы увидите NULL в параметре List<QuestionResponseVM> questResponses
.
Мои 2 цента
На самом деле вы не можете поместить форму внутри таблицы или между строками таблицы, как это. Считается недействительной структурой HTML. В любом случае использование таблиц в качестве структур для отображения данных на странице никогда не является хорошей идеей. Вместо этого вы можете использовать строку и столбцы Bootstrap.
Я не знаю, почему и что заставило вас подумать, что AJAX вам не нужно. Ваш случай похож на лучший сценарий для go с подходом AJAX! Например, набрав AJAX, пользователь может сохранять ответ на каждый вопрос отдельно. Страницу не нужно обновлять.