В случае, если это кому-нибудь пригодится, я использовал рекомендованное @bob решение с использованием PRG:
см. Пункт 13 -> ссылка .
У меня была дополнительная проблема с сообщениями, передаваемыми в VeiwBag в View, которые записывались и проверялись / загружались вручную из TempData в действиях контроллера при выполнении RedirectToAction("Action")
. В попытке упростить (а также сделать его обслуживаемым) я немного расширил этот подход для проверки и хранения / загрузки других данных. Мои методы действия выглядели примерно так:
[AcceptVerbs(HttpVerbs.Post)]
[ExportModelStateToTempData]
public ActionResult ChangePassword(ProfileViewModel pVM) {
bool result = MyChangePasswordCode(pVM.ChangePasswordViewModel);
if (result) {
ViewBag.Message = "Password change success";
else {
ModelState.AddModelError("ChangePassword", "Some password error");
}
return RedirectToAction("Index");
}
И мой Индекс Действие:
[ImportModelStateFromTempData]
public ActionResult Index() {
ProfileViewModel pVM = new ProfileViewModel { //setup }
return View(pVM);
}
Код в фильтрах действий:
// Following best practices as listed here for storing / restoring model data:
// http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#prg
public abstract class ModelStateTempDataTransfer : ActionFilterAttribute {
protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;
}
public class ExportModelStateToTempData : ModelStateTempDataTransfer {
public override void OnActionExecuted(ActionExecutedContext filterContext) {
//Only export when ModelState is not valid
if (!filterContext.Controller.ViewData.ModelState.IsValid) {
//Export if we are redirecting
if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult)) {
filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
}
}
// Added to pull message from ViewBag
if (!string.IsNullOrEmpty(filterContext.Controller.ViewBag.Message)) {
filterContext.Controller.TempData["Message"] = filterContext.Controller.ViewBag.Message;
}
base.OnActionExecuted(filterContext);
}
}
public class ImportModelStateFromTempData : ModelStateTempDataTransfer {
public override void OnActionExecuted(ActionExecutedContext filterContext) {
ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;
if (modelState != null) {
//Only Import if we are viewing
if (filterContext.Result is ViewResult) {
filterContext.Controller.ViewData.ModelState.Merge(modelState);
} else {
//Otherwise remove it.
filterContext.Controller.TempData.Remove(Key);
}
}
// Restore Viewbag message
if (!string.IsNullOrEmpty((string)filterContext.Controller.TempData["Message"])) {
filterContext.Controller.ViewBag.Message = filterContext.Controller.TempData["Message"];
}
base.OnActionExecuted(filterContext);
}
}
Я понимаю, что мои изменения здесь являются довольно очевидным расширением того, что уже было сделано с ModelState с помощью кода @ по ссылке, предоставленной @bob - но мне пришлось наткнуться на этот поток, прежде чем я даже подумал об обработке этого способ.