Почему валидаторы уровня модуля оцениваются только после валидаторов уровня свойств? - PullRequest
0 голосов
/ 30 мая 2010

Я использую валидатор уровня модуля: «PropertiesMustMatch» в моей модели представления, например так:

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

    public string Password { get; set; }

    public string PasswordConfirm { get; set; }
}

Я замечаю, что если я отправляю форму без заполненного имени, помощник ValidationSummary () возвращает только следующую ошибку:

  • Поле имени обязательно для заполнения.

Однако, если я введу Имя, , тогда ValidationSummary () вернет ошибку PropertiesMustMatch:

  • «Пароль» и «PasswordConfirm» не совпадают.

Похоже, сначала проверяются валидаторы уровня свойств, а затем валидаторы уровня модели.

Я бы предпочел, чтобы все они были проверены сразу, а ValidationSummary вернул бы:

  • Поле имени обязательно для заполнения.
  • «Password» и «PasswordConfirm» не совпадают.

Есть идеи, что я могу сделать, чтобы это исправить?

Я изучаю исходный код MVC 2, чтобы попытаться выяснить, почему это происходит.

1 Ответ

0 голосов
/ 30 мая 2010

Я нашел причину этого, но мое «решение», вероятно, нарушит нормальную обработку валидаторов. Используйте с осторожностью.

Я нашел условный оператор возврата в функции OnModelUpdated DefaultModelBinder:

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

Кажется, это решает проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...