Валидация свойства вложенной модели с помощью CompareAttribute

User:

public class User 
{
    public int Id {get; set;}
    public string FirstName {get; set;}
    public string SecondName {get; set;}
    public string Email {get; set;}
    public string Password {get; set;}
    public int Age {get; set;}
}

SignUpVM:

using System.ComponentModel.DataAnnotations;

public class SingUpVM 
{
    public User User {get; set;}
    [Compare("User.Password")] // Error
    public string ConfirmPassowrd {get; set;}
}

Ошибка SingUpVM.User.Password could not be found.

Можно ли это решить или как-то обойти?


Ответы (1 шт):

Автор решения: aepot

Доступ к свойству свойства через точку не поддерживается аттрибутом CompareAttribute. А если еще глубже копнуть в исходники, то виноват ValidationContext.

Не претендую на гениальность, но вот вариант обхода.

public class SingUpVM
{
    public User User { get; set; }

    [Compare("UserPassword")]
    public string ConfirmPassowrd { get; set; }

    [Display(Name = "User.Password")]
    public string UserPassword => User?.Password;
}

Думаю, что если это и не суперхорошее, то очень короткое решение из двух строк кода.

Если данная модель используется для сериализации, то не забудьте добавить свойству UserPassword атрибут игнорирования при сериализации, чтобы оно случайно не попало в json.

Проверка

static void Main(string[] args)
{
    var vm = new SingUpVM 
    { 
        User = new User 
        { 
            Id = 1, 
            FirstName = "FirstName", 
            SecondName = "SecondName", 
            Email = "[email protected]", 
            Password = "123", 
            Age = 12 
        }, 
        ConfirmPassowrd = "234" 
    };
    var errors = new List<ValidationResult>();
    if (!Validator.TryValidateObject(vm, new ValidationContext(vm), errors, true))
    {
        foreach (var error in errors)
        {
            Console.WriteLine(error.ErrorMessage);
        }
    }
    else
        Console.WriteLine("OK");

    Console.ReadKey();
}

Вывод в консоль

'ConfirmPassowrd' and 'User.Password' do not match.
→ Ссылка