Asp.net-Mvc

ASP.NET MVC - 如何跨 RedirectToAction 保留 ModelState 錯誤?

  • January 10, 2011

我有以下兩種操作方法(為問題而簡化):

所以,如果驗證通過,我會重定向到另一個頁面(確認)。

如果發生錯誤,我需要顯示與錯誤相同的頁面。

如果我這樣做return View(),則會顯示錯誤,但如果我這樣做return RedirectToAction(如上所述),它會失去模型錯誤。

我對這個問題並不感到驚訝,只是想知道你們如何處理這個問題?

我當然可以只返回相同的視圖而不是重定向,但是我在填充視圖數據的“創建”方法中有邏輯,我必須複製這些數據。

有什麼建議?

您需要Review在您的HttpGet操作上有相同的實例。為此,您應該在操作時將對象保存Review review在臨時變數中HttpPost,然後在HttpGet操作時將其恢復。

[HttpGet]
public ActionResult Create(string uniqueUri)
{
  //Restore
  Review review = TempData["Review"] as Review;            

  // get some stuff based on uniqueuri, set in ViewData.  
  return View(review);
}
[HttpPost]
public ActionResult Create(Review review)
{
  //Save your object
  TempData["Review"] = review;

  // validate review
  if (validatedOk)
  {
     return RedirectToAction("Details", new { postId = review.PostId});
  }  
  else
  {
     ModelState.AddModelError("ReviewErrors", "some error occured");
     return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
  }   
}

如果您希望即使在第一次執行HttpGet操作後刷新瀏覽器也能正常工作,您可以這樣做:

 Review review = TempData["Review"] as Review;  
 TempData["Review"] = review;

否則刷新按鈕對象review將為空,因為TempData["Review"].

我今天不得不自己解決這個問題,並遇到了這個問題。

有些答案很有用(使用 TempData),但並沒有真正回答手頭的問題。

我發現的最佳建議是在這篇博文中:

<http://www.jefclaes.be/2012/06/persisting-model-state-when-using-prg.html>

基本上,使用 TempData 來保存和恢復 ModelState 對象。但是,如果您將其抽象為屬性,它會更簡潔。

例如

public class SetTempDataModelStateAttribute : ActionFilterAttribute
{
   public override void OnActionExecuted(ActionExecutedContext filterContext)
   {
       base.OnActionExecuted(filterContext);         
       filterContext.Controller.TempData["ModelState"] = 
          filterContext.Controller.ViewData.ModelState;
   }
}

public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute
{
   public override void OnActionExecuting(ActionExecutingContext filterContext)
   {
       base.OnActionExecuting(filterContext);
       if (filterContext.Controller.TempData.ContainsKey("ModelState"))
       {
           filterContext.Controller.ViewData.ModelState.Merge(
               (ModelStateDictionary)filterContext.Controller.TempData["ModelState"]);
       }
   }
}

然後根據您的範例,您可以像這樣保存/恢復 ModelState:

[HttpGet]
[RestoreModelStateFromTempData]
public ActionResult Create(string uniqueUri)
{
   // get some stuff based on uniqueuri, set in ViewData.  
   return View();
}

[HttpPost]
[SetTempDataModelState]
public ActionResult Create(Review review)
{
   // validate review
   if (validatedOk)
   {
       return RedirectToAction("Details", new { postId = review.PostId});
   }  
   else
   {
       ModelState.AddModelError("ReviewErrors", "some error occured");
       return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
   }   
}

如果您還想在 TempData 中傳遞模型(如 bigb 建議的那樣),那麼您仍然可以這樣做。

引用自:https://stackoverflow.com/questions/4642845