Asp.net-Mvc

ModelState.IsValid 還是 Model.IsValid?

  • February 18, 2016

當我遇到兩種方法(我認為同樣有效)來做某事時,我正在為它編寫一個控制器和單元測試。我所有的模型都有一個 IsValid 屬性,我可以檢查它以詢問模型是否有效。

在回發到控制器操作方法時,如果模型有效,我想保存,否則我想重新顯示表單以供使用者糾正錯誤。

我最初的想法是驗證模型是否被詢問是否有效,但我意識到我也可以檢查 ModelState.IsValid。

有沒有人有任何特別的理由來看待一個與另一個?

我認為將自定義業務驗證內置到您的模型中是一種很好的方法。我處理它的方法是將任何自定義驗證錯誤添加到 ModelState:

if (ModelState.IsValid)
{
   if (!model.IsValid)
   {
      ModelState.AddModelError("The model is not valid");
   }
   else
   {
       return RedirectToAction("Index");
   }
}

return View(model);

這樣,您的視圖就可以訪問驗證錯誤,無論它們是自定義的還是內置的。

ModelState可以轉移到TempData跟隨Post-Redirect-Get。例子:

   [HttpPost]
   [ExportModelStateToTempData]
   public ActionResult Delete(int id)
   {
       if (_service.DeleteTask(id))
           return RedirectToAction(ControllerActions.Index);

       return RedirectToAction(ControllerActions.Edit, new { id });
   }

   [ImportModelStateFromTempData]
   public ActionResult Edit(int id)
   {
       var task = _service.GetTask(id);
       return View(ControllerActions.Edit, GetEditModel(task));
   }

使用者可以通過 callig /Task/Delete 操作刪除任務,但如果出現問題並出現錯誤消息,按 F5 將不會再次呼叫刪除。當ModelStateafterDelete轉移到時Edit,所有錯誤都顯示在編輯頁面上。

這是屬性導入/導出的程式碼ModelState

public abstract class ModelStateTempDataTransferAttribute : ActionFilterAttribute
{
   protected static readonly string Key = typeof(ModelStateTempDataTransferAttribute).FullName;
}

public class ExportModelStateToTempDataAttribute : ModelStateTempDataTransferAttribute
{
   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;
           }
       }

       base.OnActionExecuted(filterContext);
   }
}

public class ImportModelStateFromTempDataAttribute : ModelStateTempDataTransferAttribute
{
   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);
           }
       }

       base.OnActionExecuted(filterContext);
   }
}

做同樣的Model事情會很成問題。

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