asp.net-mvc ModelState.IsValid 还是 Model.IsValid?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5011132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:53:38  来源:igfitidea点击:

ModelState.IsValid or Model.IsValid?

asp.net-mvcvalidationmodel

提问by Andy

I'm writing a controller and unit tests for it, when I came across two ways (equally valid I think) to do something. All my models have an IsValid property, which I can check to ask the model if it's valid or not.

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

On postback to a controller action method, if the model is valid I want to save, otherwise I want to redisplay the form for the user to correct their errors.

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

My initial thought was to just verify that the model is being asked if it's valid, but I realized I could also check ModelState.IsValid.

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

Does anyone have any particular reason to look at one vs the other?

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

回答by MrDustpan

I think having custom business validation built into your model is a fine approach. The way I would handle it would be to add any custom validation errors to the ModelState:

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

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

return View(model);

That way your view has access to the validation errors regardless of whether they are custom or built in.

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

回答by LukLed

ModelStatecan be transferred to TempDatato follow Post-Redirect-Get. Example:

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));
    }

User can delete task by callig /Task/Delete action, but if something goes wrong and error message appears, pressing F5 won't call deletion again. when ModelStateafter Deleteis transferred to Edit, all errors are shown on edit page.

用户可以通过 callig /Task/Delete 操作删除任务,但如果出现问题并出现错误消息,按 F5 将不会再次调用删除。当ModelStateafterDelete转移到 时Edit,所有错误都显示在编辑页面上。

This is code for attributes importing/exporting ModelState:

这是属性导入/导出的代码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);
    }
}

Doing the same with Modelwould be very problematic.

用 with 做同样的Model事情会很成问题。

回答by Mike Brown

You can can also enumerate through the collection of errors and write the Exact error message to the output.

您还可以枚举错误集合并将确切的错误消息写入输出。

else if (!ModelState.IsValid)
{
    List<ModelError> modelErrors = new List<ModelError>();
    ModelErrorCollection errors = new ModelErrorCollection();
                              ;
    // got to the model and look at the Array of Values
    foreach (var item in ModelState)
    {
        if (item.Value.Errors.Count != 0)
        {
            // get the error
            errors = item.Value.Errors;
            modelErrors.Add(errors.Single());
        }
     }

     if (modelErrors.Count != 0)
     {
         foreach (var error in modelErrors)
         {
             Debug.WriteLine(error.ErrorMessage);
         }
      }

...

...