在控制器中编辑后,ModelState未验证嵌套模型

本文关键字:验证 嵌套 模型 ModelState 控制器 编辑 | 更新日期: 2023-09-27 17:53:42

我有两个嵌套的viewmodel:

public class FirstViewModel
{
    public SecondViewModel SecondViewModel { get; set; }
}
public class SecondViewModel
{
    [Range(1, 12)]
    public int month { get; set; }
}

如果我输入month = 13;,然后调用ModelState.IsValid(在控制器中),验证始终是true

编辑:

这是控制器:

public ActionResult Create()
{
    return PartialView(new FirstViewModel);    
}
public HttpStatusCodeResult Create (FirstViewModel viewModel){
    viewModel.SecondViewModel = new SecondViewModel();
    viewModel.SecondViewModel.month = 13;
    if (ModelState.IsValid)
    {
        return new HttpStatusCodeResult(200);
    }
    else
    {
        return new HttpStatusCodeResult(304);
    }
}

我对这个问题做了一个抽象,那些不是真正的变量。

在控制器中编辑后,ModelState未验证嵌套模型

你的问题说你"调用ModelState。在控制器中验证""。没有这样的方法,所以我假设您指的是if (ModelState.IsValid)

模型绑定过程的第一步是初始化方法的参数,在您的例子中是FirstViewModel的新实例。然后根据表单数据、路由值、查询字符串值等设置模型值,并将与模型属性相关的任何验证错误添加到ModelState中。

随后修改模型中的属性值对ModelState没有影响,因此如果month的初始值有效,那么ModelState.IsValid将返回true,无论设置viewModel.SecondViewModel.month = 13;

如果您想要重新验证您的模型,您需要使用TryUpdateModel,它返回一个bool指示更新是否成功

public HttpStatusCodeResult Create (FirstViewModel viewModel)
{
  viewModel.SecondViewModel = new SecondViewModel();
  viewModel.SecondViewModel.month = 13;
  if (TryUpdateModel(viewModel)
  {
    return new HttpStatusCodeResult(200);
  }
  else
  {
    return new HttpStatusCodeResult(304);
  }
}

因为FirstViewModel类的SecondViewModel属性是空的,所以它不会被验证。尝试在属性中添加必需的属性:

public class FirstViewModel
{
    [Required]
    public SecondViewModel SecondViewModel { get; set; }
}
public class SecondViewModel
{
    [Range(1, 12)]
    public int month { get; set; }
}

编辑

根据你的更新,我同意@StephenMuecke的观点。您不能自己实例化一个类,并期望框架为您验证它。在这种情况下,TryUpdateModel是您正在寻找的,或者您必须让框架为您实例化类。你需要传入SecondViewModel。月=13在您的请求的某个地方,以便看到它的操作

您可以随时使用这个

验证您的模型
Validator.TryValidateObject().

或者,只针对一个属性,参见

Validator.TryValidateProperty()

假设你有一个类Address

public class Address
{
    [Required]
    public string Address2 { get; set; }
    [Required]
    public string ZipCode{ get; set; }
}

可以使用这个代码片段来验证对象。所有的错误将在"results"变量中。

var addresse = new Address() { Street = null, ZipCode = null};
var context = new ValidationContext(addresse, null, null);
var results = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(addresse, context, results, true);