我有一个采取模型列表的操作。我想一次单独验证每个模型与整个模型集合。我正在尝试使用TryValidateModel,但似乎如果我的任何一个模型无效,则所有模型都无效。我的表单显示5个SurveyResponseModels(一个包含两个必需字符串和两个整数的类)。如果我完全填写所有五个模型,我将获得validCount = 5。但是,如果五个模型中的任何一个不完整(因此验证失败),我得到的validCount为0. TryValidateModel的预期行为是什么?如果是这样,关于我如何一次验证这些的任何想法?
[HttpPost]
public ActionResult Create(IList<SurveyResponseModel> respondents)
{
int validCount = 0;
foreach (SurveyResponseModel respondent in respondents)
{
if (TryValidateModel(respondent))
{
validCount++;
}
}
ModelState.AddModelError("", validCount.ToString() + " respondents passed validation");
}
答案 0 :(得分:4)
查看代码,在我看来TryValidateModel
将验证所提供对象给出的所有类型的模型,而不仅仅是该特定对象本身。此外,它返回ModelState.IsValid
属性的当前值,以便一旦存在无效模型,TryValidateModel
的所有调用都将返回false。如果你想做这样的事情,我认为你需要在特定的模型实例上自己获取并运行每个模型实例的验证器。
我还认为模型验证器已经在您手动调用它们时运行。您可以通过在循环之前查看ModelState.IsValid
的值来检查此(对于无效模型)。如果它是假的,那么这意味着验证器是由模型绑定器运行的,这就是我认为的情况。
您可以在http://aspnet.codeplex.com/找到MVC的源代码。
答案 1 :(得分:4)
TryValidateModel()
会添加验证错误列表。使用ModelState.Clear()
删除以前的错误。除非使用[ValidateInput(false)]
属性,否则验证将自动作为模型绑定过程的一部分进行。有关详细信息,请参阅https://stackoverflow.com/a/8581918/1238406。
答案 2 :(得分:1)
我在另一篇文章中看到了这种行为。
要继续使用tvanfosson的建议,我建议你在foreach之前设置一个断点,并检查ModelState以查看错误是否已存在。它们可能是:DefaultModelBinder已经放置它们。然后我可以想到两种可能性:
是的,它是ASP.NET MVC的这一部分,其中绑定逻辑并不能完成我们想要它做的事情......
答案 3 :(得分:1)
源代码:
protected internal bool TryValidateModel(object model, string prefix) {
if (model == null) {
throw new ArgumentNullException("model");
}
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(metadata, ControllerContext).Validate(null)) {
ModelState.AddModelError(DefaultModelBinder.CreateSubPropertyName(prefix, validationResult.MemberName), validationResult.Message);
}
return ModelState.IsValid;
}
如果错误,它将始终返回false。