Вот как я обычно справляюсь с этой ситуацией. Для модели представления я использую только один, EditUserModel, поскольку поддержка 3 классов не окупается, только 1-2 свойства различны, и, на мой взгляд, модель представления не так важна, я просто быть прагматичным. В вашем случае EditUserModel должен выглядеть примерно так
public class EditUserModel
{
public int Id {get;set} //used when modifying user
public string Name {get;set;}
public string Password {get;set;}
public string ConfirmPassword {get;set;} //this is optionally
}
Эта модель передается контроллеру, и я лично использую подход DDD (как образ мыслей) и, скажем, модель предметной области, которая выглядит следующим образом (она основана на коде, который я на самом деле использую)
public class Password
{
public Password(string value,string salt)
{
//you can apply basic validation rules if you want\\
Hash=(salt+value).Sha256(); //a variant of hashing and an extension method
Salt=salt;
}
public string Hash {get;private set;}
public string Salt {get;private set;}
}
public class Member
{
public Member(string name, Password pwd)
{
Name=name;
Password=pwd;
Created= DateTime.Now;
}
public Member(int id,DateTime created,string name,Password p)
{
Id = id;
Created = created;
_name = name;
_password = p;
}
public int Id { get; set; }
private string _name;
public string Name
{
get { return _name; }
set
{
LastModified = DateTime.Now;
_name = value;
}
}
private Password _password;
public Password Password
{
get { return _password; }
set
{
_password = value;
LastModified = DateTime.Now;
}
}
public DateTime Created {get;private set;}
public DateTime LastModified {get;private set;}
}
Первый раз при создании пользователя
var user= new Member(model.Name,new Password(model.Password,"a salt"));
repository.Save(user);
При обновлении
var user= repository.GetUser(int id);
user.Name=model.Name;
if (!string.IsNullOrEmpty(model.Password)) user.Password= new Password(model.Password,"a salt");
repository.Save(user);
В репозитории (обратите внимание, что у меня нет большого опыта работы с EF, поэтому этот код, безусловно, можно оптимизировать)
public void Save(Member user)
{
using (var dc = new DbContext())
{
if (user.Id==0)
{
//do insert, all this can be handled via automapper
var u= new User();
u.Name=user.Name;
u.Password=user.Password.Hash;
u.Created=user.Created;
u.LastModified=user.LastModifed;
dc.Users.Add(u);
dc.SaveChanges();
user.Id=u.Id;
}
else
{
//do edit
var u= dc.Users.First(d=>d.Id==user.Id);
//map values \\
dc.Users.SaveChanges();// EF should detect if something was changed and save only changes
}
}
}
public Member GetUser(int id)
{
//get User from DbContext \\
var m= new Member(id,user.Created,user.Name,new Password(user.Password,"my salt"));
return m;
}
Это поспешный код, и все может быть улучшено, но позвольте мне рассказать, почему такой «сложный» подход. Прежде всего, мы имеем более четкое различие между уровнями ответственности, модель представления обрабатывает все необходимое для отображения и отправки данных в контроллер, а модель предметной области не смешивается с моделью постоянства (модель EF). Вы можете довольно легко изменить технику хэширования паролей, и создается / последний измененный материал обрабатывается там, где действительно происходят изменения. Когда вы начнете добавлять больше функциональности, этот дизайн значительно облегчит вам работу.
Основная цель - ясность и удобство обслуживания, и в зависимости от использования вы можете выбрать другой подход, например, обновление пользователя с помощью команд (вы отправляете в хранилище команду для изменения имени или пароля)
Хорошо, я закончил:)