Html.Hidden для случайного получения информации о модели
У нас возникла проблема с Html.HiddenFor в MVC3, которая иногда неправильно связывалась. Мы вообще не можем воспроизвести его, но мы видим, как в нашем журнале появляются нули, и это сводит нас с ума.
У нас есть следующая модель и структура контроллера:
public class DummyController
{
[HttpGet]
public ActionResult ReturnAPage(int NumericID)
{
//NumericID should never be 0 or negative, but let's check to make sure
if (NumericID < 1)
{
return RedirectToAction("TracyJordanStabbingRobot");
}
return View("DummyView", new DummyViewModel(NumericID));
}
[HttpPost]
public ActionResult TakePageSubmission(DummyViewModel model)
{
//AnObject relies on having a non-zero ID
ComplexObject AnObject = new ComplexObject(model.NumericID);
AnObject.UseMe();
}
}
public class DummyViewModel
{
public DummyViewModel() {}
public DummyViewModel(int ID)
{
NumericID = ID;
}
public int NumericID { get; set; }
}
... и следующая структура представления:
DummyView.cshtml
@model DummyViewModel
<html>
<head></head>
<body>
<p>THIS IS A VIEW!</p>
<form id="DummyViewForm" action="/RouteTo/TakePageSubmission" method="post">
@Html.Partial("_PartialDummyView", Model)
<input type="submit" value="Submit This!" />
</form>
</body>
</html>
_PartialDummyView.cshtml
@model DummyViewModel
<p>Heard you like views...</p>
@Html.HiddenFor(model => model.NumericID)
Учитывая, что мы проверяем наличие значений меньше нуля в начальном действии контроллера, очевидно, что @Html.HiddenFor(model => model.NumericID)
никогда не должно иметь значение меньше нуля.
Это, как говорится, когда мы используем AnObject
в TakePageSubmission
действие, мы получаем нулевые ошибки ссылки.
Когда мы копались в регистрации model.NumericID
значение, мы видим, что оно приходит как ноль, что не должно быть возможным, учитывая, что DummyView может быть доступен только с ненулевым значением.
Мы немного озадачены, и, поскольку мы не можем надежно воспроизвести проблему, мы понятия не имеем, что могло ее вызвать. Кто-нибудь сталкивался с чем-то подобным раньше?
Редактировать: мы выполняем проверку ModelState для сообщения формы, но мы не проверяем, имеет ли значение NumericID значение 0. Когда мы проверили это, модель показалась недействительной, что просто доказывает, что HiddenFor получает установить неправильно. Кроме того, маршрут к странице на самом деле включает в себя NumericID, поэтому, например, мы видели это на:
http://our.site.com/RouteToReturnAPage/1736/
... где параметр действия задан четко, модель построена правильно, но по неизвестной причине значение HiddenFor NumericID равно 0. Это действительно сбивает с толку.
2 ответа
Привязки по умолчанию с 0 значениями из MVC View'ing на той же странице после публикации, думая, что он перезагружает то же представление из-за ошибки во время публикации. Правильная привязка произойдет при вызове загрузки / действия к другому вызову действия.
Есть обходной путь, чтобы ModelState.Clear();
перед перезагрузкой просмотра.
Кроме того, вообще не используйте помощников для создания скрытых полей, что-то вроде:
<input type="hidden" value="@Model.NumericID" id="NumericID" name="NumericID" />
Сначала в вашей модели отсутствует конструктор по умолчанию. Без этого приложение выдает исключение при связывании.
Вы можете воспроизвести ошибку, отредактировав скрытое поле на стороне клиента. Таким образом, пользователь может изменить идентификатор на 0 или любое другое значение. Если вы не запускаете приложение в распределенной среде, используйте TempData для передачи идентификатора между действиями. Таким образом, вы будете защищены от несанкционированного доступа к данным.
TempData["NumericID"] = NumericID;