ModelState.IsValid或Model.IsValid?

And*_*ndy 11 validation asp.net-mvc model

我正在编写一个控制器和单元测试,当我遇到两种方式(我认为同样有效)做某事.我的所有模型都有一个IsValid属性,我可以检查它是否有效.

在回发到控制器操作方法时,如果模型有效,我想保存,否则我想重新显示表单以供用户更正错误.

我最初的想法只是验证模型是否被问及是否有效,但我意识到我还可以检查ModelState.IsValid.

有没有人有任何特别的理由看一个与另一个?

MrD*_*pan 12

我认为在您的模型中内置自定义业务验证是一种很好的方法.我处理它的方法是将任何自定义验证错误添加到ModelState:

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

return View(model);
Run Code Online (Sandbox Code Playgroud)

这样,您的视图就可以访问验证错误,无论它们是自定义还是内置.


Luk*_*Led 7

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));
    }
Run Code Online (Sandbox Code Playgroud)

用户可以通过callig/Task/Delete操作删除任务,但如果出现问题并出现错误信息,按F5将不会再次调用删除.当ModelState之后Delete被转移到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);
    }
}
Run Code Online (Sandbox Code Playgroud)

做同样的Model事情会很成问题.