Как я могу поддерживать ошибки ModelState при использовании RedirectToAction?
У меня есть код, который сохраняет билет в нашей системе. Если есть ошибка, это делает RedirectToAction. Проблема в том, что, похоже, у меня нет ошибок в новом действии. Как я могу это исправить?
ModelState.AddModelError("_FORM", "Unable to save ticket");
ModelState.AddModelError("_FORM", "Phone number was invalid.");
ModelState.AddModelError("_FORM", "Lane number is required.");
return RedirectToAction("CreateStep", "Ticket");
Я знаю, что некоторые предложили использовать TempData, но как я могу получить каждую ошибку из ModelState?
Спасибо.
Ответы
Ответ 1
Шаблон PRG в порядке, но я сделал это:
Базовый контроллер:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (TempData["ModelState"] != null && !ModelState.Equals(TempData["ModelState"]))
ModelState.Merge((ModelStateDictionary)TempData["ModelState"]);
base.OnActionExecuted(filterContext);
}
Действие (я использую xVal):
try
{
user.Login();
AuthenticationManager.SignIn(user);
}
catch (RulesException rex)
{
// on bad login
rex.AddModelStateErrors(ModelState, "user");
TempData["ModelState"] = ModelState;
return Redirect(Request.UrlReferrer.ToString());
}
Действие генерирует исключение, добавляет ModelState в TempData и перенаправляет обратно на реферер. Поскольку действие обнаружено, OnActionExecuted все еще выполняется, но первый раз вокруг ModelState совпадает с TempData [ "ModelState" ], поэтому вы не хотите сливаться с самим собой. Когда выполняется действие перенаправления, OnActionExecuted снова срабатывает. На этот раз, если что-нибудь в TempData [ "ModelState" ], оно сливается с этим действием ModelState.
Вы можете развернуть его на несколько моделей с помощью TempData [ "ModelState.user" ] = ModelState и затем слить каждый объект TempData, который начинается с ModelState.
Ответ 2
Я знаю, что эта ветка устарела, но этот блог о лучших рекомендациях ASP.NET содержит несколько отличных предложений.
# 13 на странице имеет дело с использованием 2 фильтров действий для сохранения и восстановления ModelState
между переадресациями.
Это образец, который использует моя работа, и мне это нравится.
Здесь приведен упрощенный пример:
[ImportModelStateFromTempData]
public ActionResult Dashboard()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult Dashboard(string data)
{
if (ValidateData(data))
{
try
{
_service.Submit(data);
}
catch (Exception e)
{
ModelState.AddModelError(ModelStateException, e);
}
}
return RedirectToAction("Dashboard");
}
Ответ 3
В этом блоге описано, как вы можете реализовать PRG-шаблон в MVC
http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx
HTH
Ответ 4
Используйте коллекцию TempData []
Tempdata хранится от одного запроса до следующего, а затем его нет.
Ответ 5
Что я сделал, чтобы поддерживать свой ModelState независимо от того, куда я иду с переадресацией, следующее:
-
В вашей модели добавьте:
public ModelStateDictionary modelstate { get; set; }
-
В конструкторе модели добавьте:
this.modelstate = new System.Web.Mvc.ModelStateDictionary();
-
Пример сообщения с моей моделью под названием Models.ContactInformation:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult contact(Models.ContactInformation con)
{
if (string.IsNullOrEmpty(con.SelectedAgencySelectorType))
{
ModelState.AddModelError("", "You did not select an agency type.");
}
con.modelstate = ModelState;
TempData["contact"] = con;
if (!ModelState.IsValid) return RedirectToAction("contactinformation", "reports");
//do stuff
return RedirectToAction("contactinformation", "reports");
}
-
Итак, теперь у ваших tempdata есть ваша модель и модель, как есть.
-
Следующее - это мое мнение, которое агностически относится к состоянию чего-либо, если у него нет чего-то. Здесь код:
[HttpGet]
public ActionResult contactinformation()
{
//try cast to model
var m = new Models.ContactInformation();
if (TempData["contact"] is Models.ContactInformation) m = (Models.ContactInformation)TempData["contact"];
//restore modelstate if needed
if (!m.modelstate.IsValid)
{
foreach (ModelState item in m.modelstate.Values)
{
foreach (ModelError err in item.Errors)
{
ModelState.AddModelError("", err.ErrorMessage.ToString());
}
}
}
return View(m);
}
Ответ 6
Я считаю, что вы теряете свое состояние модели, когда выполняете перенаправление. Возможно, вы могли бы переписать свою логику на что-то вроде:
public ActionResult Save()
{
// your code...
if(saveSucceeded)
{
return View("Saved");
}
else
{
return View("Create");
}
}
И обычный способ получить сообщение об ошибке:
<%= Html.ValidationMessage("property_name") %>