I'm trying to understand and figure good practices for designing your app/domain models (POCOs/DTOs).
Let's say I have the following database table, Account:
UserID int
Email varchar(50)
PasswordHash varchar(250)
PasswordSalt varchar(250)
Of course, EF4 would build the entity like so:
public class Account
{
public int UserID { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public string PasswordSalt { get; set; }
}
Now, let's say I have a view model for registering a new user, which may look something like so:
public class RegistrationViewModel
{
public string Email { get; set; }
public string Password { get; set; }
}
Lastly, I have a service which needs to register the user:
public class RegistrationService
{
public void RegisterUser(??? registration)
{
// Do stuff to register user
}
}
I'm trying to figure out what to pass into the RegisterUser method. The view model is, of course, located under my web app (presentation layer), so I do not want this getting passed to my service.
So, I'm thinking one of four possibilities:
1) Set up a service model that is similar, if not identical, to the RegistrationViewModel, and use this:
public class RegistrationServiceModel
{
public string Email { get; set; }
public string Password { get; set; }
}
public class RegistrationService
{
public void RegisterUser(RegistrationServiceModel registration)
{
// Do stuff to register user
}
}
2) Set up an interface of the model, and inherit this in my view model, and set up my method to accept the interface:
public interface IRegistrationModel
{
string Email;
string Password;
}
public class RegistrationServiceModel : IRegistrationModel
{
public string Email { get; set; }
public string Password { get; set; }
}
public class RegistrationService
{
public void RegisterUser(IRegistrationModel registration)
{
// Do stuff to register user
}
}
3) Pass in the Account entity, doing the RegistrationViewModel-to-Account mapping in my controller:
public class RegistrationService
{
public void RegisterUser(Account account)
{
// Do stuff to register user
}
}
4) Move my view model out of the presentation into a domain/service layer, and pass that into the service method:
public class RegistrationService
{
public void RegisterUser(RegistrationViewModel account)
{
// Do stuff to register user
}
}
None of these three scenarios seem ideal, as I see problems in each of them. So I'm wondering if there's another method I can't think of.
What are good practices for this?
Thanks in advance.
You never pass a view model to the service. A service doesn't even know about the existence of a view model that you might have defined in your presentation tier. A service works with domain models.
Use Auto mapper to map between view model and domain model and vice versa.
Personally, I've never heard of service models in DDD (view models for services).
In this case it makes perfect sense to use a DTO (Data Transfer Object). You can create an
AccountDto
class at the service layer and use it to pass the registration data down to the service. It might be similar to the ViewModel in some cases, but generally you can show much more in your View than is required to create a user. To further illustrate the point, your ViewModel will probably at least look something like this:While your DTO will only require the
Email
andPassword
properties.So as you see, the
ViewModel
only contains data needed for theView
. The email validation and password comparison logic happens in your Web layer. You use the DTO to get get only email and password to the Service. And then at the service layer you hash the password, populate your Entity object and persist the values to the database.Use 3rd option, for sure. As šljaker said, Service should be unaware of presentation part of application (which your ViewModel is a part of).
Sure, as well, don't overcomplicate things around by including tons of transition models like
RegistrationServiceModel
or - even worse -IRegistrationModel
(last one will lead to "interface explosion" one day).So:
ViewModel
per Controller Action if necessary. The side-effect benefit of strict ViewModels (those which are 1:1 with your View) is complete absence of over-posting and under-posting problems. It depends on your concrete situation/taste though.ViewModel
orFormCollection
to your entity in either Controller action or customIModelBinder
.