I am using ASP.NET MVC 3 and Entity Framework 4.1 first.
Say I have a User object:
public class User { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Password { get; set; } }
When editing in my UserController I want to add the PasswordConfirmation field and make sure PasswordConfirmation == Password
1. The composition
My first attempt:
public class EditUserModel { [Required] public User User { get; set; } [Compare("User.Password", ErrorMessage = "Passwords don't match.")] public string PasswordConfirmation { get; set; } }
In this case, client-side validation works but ( Edit: client-side validation work was a coincidence.) Does not work and server-side validation failed with the following message: Could not find a property named User.Password
Edit: I think the best solution in this case would be to create a custom CompareAttribute
Implement 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]; } }
In this case, server-side validation works , but client-side validation no longer works . Implementing IClientValidatable seems too complicated, and I prefer not to check on the client side in this case.
2. By inheritance
public class EditUserModel : User { [Compare("Password", ErrorMessage = "Passwords don't match.")] public string PasswordConfirmation { get; set; } }
When I try to directly save EditUserModel using EF, this will not work, I get some error message in the EditUserModel metadata, so I use AutoMapper to convert from User to EditUserModel and back. This solution works , but it is more complicated because I need to convert from model to view model and back.
3. By duplication
(proposed by Malte Clasen)
The view model will have all the model properties plus additional ones. AutoMapper can be used to convert from one to another.
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; } }
This is the solution I least like because of code duplication (DRY)
Questions
What are the advantages and disadvantages of inheritance, compilation and duplication in this case?
Is there an easy way to check both on the client side and on the server side without converting the model into a view model and back?