#asp.net-mvc-3 #razor #mvc-editor-templates
#asp.net-mvc-3 #razor #mvc-editor-templates
Вопрос:
Если бы это была проблема с MVC3, там были бы сообщения об этом, но я не могу найти ни одного. Должно быть, я делаю что-то не так. У меня есть простое представление (Index.cshtml), которое выполняет итерацию по списку с использованием цикла for. На каждой итерации я вывожу два текстовых ввода со значениями из одного из элементов списка.
@{Html.BeginForm();}
@Html.Encode("n")
@for (int i = 0; i < Model.SortOptions.Count; i )
{
@Html.TextBoxFor(m => m.SortOptions[i].ColumnName);
@Html.Encode("n");
@Html.TextBoxFor(m => m.SortOptions[i].Direction);
@Html.Encode("n");
}
<input type="submit" value="Submit" />
@{Html.EndForm();}
У меня есть два контроллера для просмотра, один для запросов GET и один для POST. Версия POST добавляет в список элементы, отличные от версии GET. Вот тут-то и возникает проблема. После перезагрузки страницы текстовые поля имеют то же значение, что и при загрузке страницы в GET.
Сначала я подумал, что это, должно быть, проблема с кэшированием, но если я изменю код (как показано ниже), чтобы вручную добавить вводимый текст и ввести значения в html, новые значения будут отправлены в браузер.
@{Html.BeginForm();}
@Html.Encode("n")
@for (int i = 0; i < Model.SortOptions.Count; i )
{
var columnNameName = string.Format("SortOptions[{0}].ColumnName", i);
var columnNameID = string.Format("SortOptions_{0}__ColumnName", i);
var directionName = string.Format("SortOptions[{0}].Direction", i);
var directionID = string.Format("SortOptions_{0}__Direction", i);
<input type="hidden" name="@columnNameName" id="@columnNameID" value="@Model.SortOptions[i].ColumnName" />
<input type="hidden" name="@directionName" id="@directionID" value="@Model.SortOptions[i].Direction" />
}
<input type="submit" value="Submit" />
@{Html.EndForm();}
Я прошелся по коду, чтобы убедиться, что модель содержит ожидаемые значения на момент их отправки в представление. Я даже проверил значения списка, пройдясь по коду в представлении. Кажется, что он имеет правильные значения, но когда я просматриваю его в браузере, у него есть значения, которые должны соответствовать моменту, когда страница ответила на запрос GET. Это проблема с шаблонами редактора? Я только начал использовать mvc3 и движок razor, поэтому я многого не знаю. Буду признателен за любую помощь.
—— ОБНОВЛЕНИЕ: ДОБАВЛЕН код КОНТРОЛЛЕРА —-
[HttpGet]
public ActionResult Index()
{
var inv = new InventoryEntities();
var model = new IndexModel(inv);
model.SortOptions = new List<SortOption>();
model.SortOptions.Add(new SortOption { ColumnName = "Model", Direction = SortDirection.Ascending });
model.SortOptions.Add(new SortOption { ColumnName = "Make", Direction = SortDirection.Ascending });
//Load data
model.LoadEquipmentList();
return View(model);
}
[HttpPost]
[OutputCache(Duration = 1)]
public ActionResult Index(List<SortOption> sortOptions, SortOption sort)
{
var inv = new InventoryEntities();
var model = new IndexModel(inv);
ModelState.Remove("SortOptions");
model.SortOptions = new List<SortOption>();
model.SortOptions.Add(new SortOption { ColumnName = "Type", Direction = SortDirection.Descending });
model.SortOptions.Add(new SortOption { ColumnName = "SubType", Direction = SortDirection.Descending });
model.EquipmentList = new List<EquipmentListItem>();
model.EquipmentList.Add(new EquipmentListItem { ID = 3, AssignedTo = "Mike", Location = "Home", Make = "Ford", Model = "Pinto", Selected = false, SubType = "Car", Type = "Vehicle" });
return View(model);
}
Комментарии:
1. Можете ли вы опубликовать код действия контроллера?
2. Теперь опубликован код контроллера.
Ответ №1:
Помните, что помощники Html, такие как TextBoxFor
, сначала используют состояние модели при привязке своих значений, а затем модель. Давайте рассмотрим очень простой пример, чтобы проиллюстрировать, что это значит:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel { Name = "foo" });
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
model.Name = "bar";
return View(model);
}
}
и представление:
@model MyViewModel
@using (Html.BeginForm())
{
@Html.TextBoxFor(x => x.Name)
<input type="submit" value="OK" />
}
Теперь, когда вы отправляете форму, вы ожидаете, что значение в текстовом поле изменится на "bar"
, поскольку это то, что вы ввели в свое действие POST, но значение не меняется. Это потому, что в состоянии модели уже есть значение с ключом Name
, которое содержит то, что ввел пользователь. Итак, если вы хотите, чтобы это сработало, вам нужно удалить исходное значение из состояния модели:
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// remove the original value if you intend to modify it here
ModelState.Remove("Name");
model.Name = "bar";
return View(model);
}
То же самое происходит и в вашем сценарии. Поэтому вам может потребоваться удалить значения, которые вы изменяете, из состояния модели в вашем действии POST.
Комментарии:
1. Я пытался использовать ModelState. Удалить, безуспешно. Я получаю те же результаты. Я обновлю свой пост кодом для двух методов контроллера.
2. Хорошо, это было в основном проблемой. Я все еще не до конца понимаю, как работает modelstate, но если я добавлю «ModelState. Очистить();» в начале метода контроллера проблема устраняется. Спасибо, что указали мне правильное направление.
Ответ №2:
Мне бросается в глаза пара вещей — не видя немного больше, трудно сказать, но … оба они могут быть переписаны как таковые. Дополнительные @
символы не нужны.
@using(Html.BeginForm()) {
Html.Encode("n")
for (int i = 0; i < Model.SortOptions.Count; i ) {
Html.TextBoxFor(m => m.SortOptions[i].ColumnName);
Html.Encode("n");
Html.TextBoxFor(m => m.SortOptions[i].Direction);
Html.Encode("n");
}
<input type="submit" value="Submit" />
}
@using (Html.BeginForm()) {
Html.Encode("n");
for (int i = 0; i < Model.SortOptions.Count; i ) {
var columnNameName = string.Format("SortOptions[{0}].ColumnName", i);
var columnNameID = string.Format("SortOptions_{0}__ColumnName", i);
var directionName = string.Format("SortOptions[{0}].Direction", i);
var directionID = string.Format("SortOptions_{0}__Direction", i);
<input type="hidden" name="@columnNameName" id="@columnNameID" value="@Model.SortOptions[i].ColumnName" />
<input type="hidden" name="@directionName" id="@directionID" value="@Model.SortOptions[i].Direction" />
}
<input type="submit" value="Submit" />
}
В остальном ваш материал выглядит правильно, и я не вижу ничего неправильного в своей голове.
Комментарии:
1. Спасибо за совет по использованию @. Я использовал MVC2 для двух проектов, но это первый проект, использующий MVC3 и razor.