ASP.Net Проблема с обратной отправкой MVC ModelState / Html.TextBox
-
08-07-2019 - |
Вопрос
У меня возникла проблема с формой, которую я пытаюсь опубликовать.В сценарии, когда форма не проходит проверку, я использую стандартный маршрут вызова ModelState.AddModelError()
затем возвращается результат просмотра.
Дело в том, что помощники HTML. * должны получать отправленное значение при рендеринге, и я замечаю, что мои текстовые поля делают это, ТОЛЬКО если я включаю их в список параметров действия обратной отправки, что не должно требоваться, поскольку в некоторых формах слишком много полей, чтобы захотеть перечислить их все в качестве параметров.
Мой код действия примерно таков:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name)
{
var dataDefinition = ...
// do some validation stuff
if (!ModelState.IsValid)
{
// manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P
// ...
return View(dataDefinition);
}
}
Теперь dataDefinition (который является объектом LINQ to SQL) имеет поле Минимальный объем, обрабатывается в представлении этой строкой:
Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%>
Тем не менее, когда представление визуализируется после неудачной проверки ModelState, значение, введенное в него на исходной странице, которую мы опубликовали, не сохраняется, ЕСЛИ я не включу его в качестве параметра в метод обратной передачи.Буквально, я могу "решить проблему", сделав это:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name, string minVolume)
По какой-то причине это приведет к сохранению значения поля.Мне это кажется глупым, потому что моя форма содержит намного больше значений, чем просто это, и мне не нужно добавлять параметр только для этого поля.
Есть какие-нибудь идеи?
Решение
Может быть, это ваш код:
<%= Html.TextBox("MinVolume", null, new { size = 5 })%>
.. имеет ноль
для значения по умолчанию param? Возможно, если вы измените null
на Model.MinVolume
, оно сохранит значение. Вот так:
<%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%>
Я не уверен, что ваше действие возвращает значение MinVolume
в модели tho. Если это произойдет, вышеупомянутое должно работать. Иначе вам может понадобиться немного изменить рефакторинг.
Другие советы
О боже, я только что улучшил дизайн своего приложения.Проблема возникает из-за того, что у вас есть пользовательская проверка (у меня тоже).Вы должны добавить после
ModelState.AddModelError()
это
ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]);
С учетом того, что это должно быть
Mimum:<%=Html.Textbox("MinVolume")%>
До сих пор не уверен, почему это работает, но у меня это сработало.
Какой ключ вы используете, когда устанавливаете значение в ModelState при ошибке? Код, который устанавливает параметр значения для TextBox, выглядит следующим образом:
Соответствующая часть загруженного кода платформы .
string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue);
Как вы можете видеть, существует ли значение попытки, оно будет использовать его, но только если доступен тот же ключ.
Я знаю, что это работает, потому что у меня есть действие, которое не принимает параметров и получает значения непосредственно из ValueProvider, и оно использует AddModelError, чтобы указать ошибки проверки. Я уверен, что значения в моих текстовых окнах сохраняются.
РЕДАКТИРОВАТЬ . Чтобы значения были сохранены, их необходимо каким-то образом связать с моделью. Один из способов сделать это - добавить их в список параметров. Другой способ - использовать UpdateModel (с именами параметров в белом списке или без белого). Третий способ - добавить параметр явно в модель, как в ответе @ Jenea. Поскольку помощник извлекает только из состояния модели, они должны быть там, чтобы значения были сохранены. Он не смотрит на свойство формы запроса.
Как я понимаю, решение таково:
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(int id, FormCollection form)
{
T itemToUpdate = repository.Get(id);
UpdateModel(itemToUpdate, form.ToValueProvider());
if (itemToUpdate.IsValid())
{
repository.SaveOrUpdate(itemToUpdate);
return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
}
repository.DbContext.RollbackTransaction();
return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
}
удачи!
Другое решение, если вы наберете вид:
<%var minVolume=Request["MinVolume"]??"";%>
<%=Html.Textbox("MinVolume",minVolume,new {size=5})%>
Пожалуйста, обратитесь к этой статье, чтобы увидеть различные способы обработки обратной передачи в ASP.NET MVC