Архитектура ASP.NET MVC: ViewModel по составу, наследованию или дублированию?

Я использую ASP.NET MVC 3 и Entity Framework 4.1 Code First.

Допустим, у меня есть сущность User :

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }        
}

При редактировании в моем UserController Я хочу добавить поле PasswordConfirmation и убедиться, что PasswordConfirmation == Password

1. По составу

Моя первая попытка была:

public class EditUserModel
{
    [Required]
    public User User { get; set; }

    [Compare("User.Password", ErrorMessage = "Passwords don't match.")]
    public string PasswordConfirmation { get; set; }
}

В этом случае проверка на стороне клиента работает, но ( Изменить: проверка на стороне клиента была случайностью.) не работает. не работает , а проверка на стороне сервера завершается неудачно со следующим сообщением: Не удалось найти свойство с именем User.Password

Изменить: Я считаю лучшим решением в в этом случае можно было бы создать пользовательский CompareAttribute

, реализующий IValidatableObject

public class EditUserModel : IValidatableObject
{
    [Required]
    public User User { get; set; }
    public string PasswordConfirmation { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if(this.PasswordConfirmation != this.User.Password)
            return new[] { new ValidationResult("Passwords don't match", new[] { "PasswordConfirmation " }) };

        return new ValidationResult[0];
    }
}

В этом случае проверка на стороне сервера работает , но проверка на стороне клиента не работает больше нет. Реализация IClientValidatable кажется слишком сложной, и я предпочитаю не проводить валидацию на стороне клиента в этом случае.

2. По наследству

public class EditUserModel : User
{
    [Compare("Password", ErrorMessage = "Passwords don't match.")]
    public string PasswordConfirmation  { get; set; }
}

При попытке напрямую сохранить EditUserModel с использованием EF это не работает,Я получаю сообщение об ошибке в метаданных EditUserModel , поэтому я использую AutoMapper для преобразования из User в EditUserModel и обратно. Это решение работает , но оно более сложное, потому что мне нужно преобразовать модель в модель представления и обратно.

3. Путем дублирования

(предложено Мальте Класеном)

Модель представления будет иметь все свойства модели плюс дополнительные. AutoMapper может использоваться для преобразования из одного в другой.

public class EditUserModel {    
  public string Name { get; set; }    
  public string Email { get; set; }    
  public string Password { get; set; }   
  [Compare("Password", ErrorMessage = "Passwords don't match.")]     
  public string ConfirmPassword { get; set; }        
}

Это решение, которое мне нравится меньше всего из-за дублирования кода (DRY)

Вопросы

Каковы плюсы и минусы наследования , составление и дублирование в этом случае?

Есть ли простой способ обеспечить валидацию на стороне клиента и на стороне сервера без необходимости преобразовывать модель в модель представления и обратно?

54
задан Catalin DICU 5 August 2011 в 01:02
поделиться