0

我在我的视图模型上使用模块级验证器:'PropertiesMustMatch',如下所示:

[PropertiesMustMatch("Password", "PasswordConfirm")]
public class HomeIndex
{
    [Required]
    public string Name { get; set; }

    public string Password { get; set; }

    public string PasswordConfirm { get; set; }
}

我注意到,如果我提交未填写名称的表单,则 ValidationSummary() 助手仅返回以下错误:

  • 名称字段是必需的。

但是,如果我填写 Name,那么ValidationSummary() 将返回 PropertiesMustMatch 错误:

  • “密码”和“密码确认”不匹配。

所以看起来首先评估的是属性级验证器,然后是模型级验证器。

如果它们都被一次验证,我会更喜欢,并且 ValidationSummary 会返回:

  • 名称字段是必需的。
  • “密码”和“密码确认”不匹配。

有什么想法可以解决这个问题吗?

我正在研究 MVC 2 源代码,试图确定为什么会发生这种情况。

4

1 回答 1

0

我找到了造成这种情况的原因,但我的“解决方案”可能会破坏验证器的正常处理。谨慎使用。

我在 DefaultModelBinder 的 OnModelUpdated 函数中发现了一个条件返回语句:

protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    IDataErrorInfo errorProvider = bindingContext.Model as IDataErrorInfo;
    if (errorProvider != null)
    {
        string errorText = errorProvider.Error;
        if (!String.IsNullOrEmpty(errorText))
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorText);
        }
    }

    // BEGIN CONDITION
    if (!IsModelValid(bindingContext))
    {
        return;
    }
    // END CONDITION

    foreach (ModelValidator validator in bindingContext.ModelMetadata.GetValidators(controllerContext))
    {
        foreach (ModelValidationResult validationResult in validator.Validate(null))
        {
            bindingContext.ModelState.AddModelError(CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName), validationResult.Message);
        }
    }
}

如果我理解这段代码(我可能不理解),似乎 MVC 团队打算在这一点上跳过模型验证器。

我已经制作了自己的自定义 ModelBinder,在其中我重新运行了条件本来可以避免的代码:

public class CustomModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        foreach (ModelValidator validator in bindingContext.ModelMetadata.GetValidators(controllerContext))
        {
            foreach (ModelValidationResult validationResult in validator.Validate(null))
            {
                bindingContext.ModelState.AddModelError(CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName), validationResult.Message);
            }
        }
    }
}

这似乎可以解决问题。

于 2010-05-30T05:11:03.973 回答