EF Entities vs. Service Models vs. View Models (MVC) - asp.net-mvc

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).

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:
Have a Domain entity (POCO entity that is persisted with Entity Framework or NHibernate or NoRM or whatever).
Have a ViewModel that represents your domain model in given context. Don't hesitate to make a 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.
Use DataAnnotation attributes with your ViewModels to provide basic validation (remember to validate business rules too but it should sit behind the wire - inside Services/Repositories layer).
Don't let App Service ever know about ViewModels. Create a domain entity instance and feed it to the Service instead (to validate/persist).
Use AutoMapper as an option to quicky map from your domain entities to ViewModels.
Map from incoming ViewModel or FormCollection to your entity in either Controller action or custom IModelBinder.
(Optionally) I'd recommend to follow the Thunderdome Principle. It's a really really convenient usage of ViewModels.

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:
public class RegistrationViewModel
{
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
[Compare("Password")]
public string RepeatPassword { get; set; }
}
While your DTO will only require the Email and Password properties.
public class AccountDto
{
public string Email { get; set; }
public string Password { get; set; }
}
So as you see, the ViewModel only contains data needed for the View. 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.

Related

Does this violate the DRY principle?

I have 3 domain models - Item, ItemProductLine, and ProductLine. Each of these map to already existing database tables. I also have a view model that I use in my view.
Domain models:
public class Item
{
public string itemId { get; set; }
public string itemDescription { get; set; }
public float unitPrice { get; set; }
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
}
public class ItemProductLine
{
public string itemId { get; set; }
public String productLineId { get; set; }
// more fields
public virtual ProductLine productLine { get; set; }
}
public class ProductLine
{
public string productLineId { get; set; }
public string productLine { get; set; }
// more fields
}
View model:
public class ItemViewModel
{
public string itemNumber { get; set; }
public String itemDescription { get; set; }
public Double unitPrice { get; set; }
public string productLine { get; set; }
}
My current query is:
from item in dbContext.Items
where unitPrice > 10
select new ItemViewModel()
{
itemNumber = item.itemNumber
itemDescription = item.itemDescription
unitPrice = item.unitPrice
productLine = item.itemProductLine.productLine.productLine
}
I currently have this query in the controller, but I am refactoring the code. I want to put the query code in a repository class in a data access layer. From what I've read, I should not reference any view models in that layer. If I change select new ItemViewModel() to select new Item(), it will return the error:
The entity or complex type 'proj.DAL.Item' cannot be constructed in a LINQ to Entities query.
A solution I have seen is to create a data transfer object (DTO) to transfer data from my domain model to my view model.
However, by doing this, I would have 3 copies of the data. If I need to add another database field and display it, I need to update 3 files. I believe I am violating the DRY principle. Is it inevitable to violate the DRY principle when using DTOs and view models? If not, can you provide an example of how to refactor this to have DRY code?
Having multiple models is not a DRY violation however your code breaks the Separation of Concerns principle because the domain model is the same with (or built upon, read: coupled to) persistence model. You should keep your models separated for each layer and use a tool like automapper to map them. This prevents the model to serve more than one purpose.
It looks like repeating yourself, but in fact you are keeping your layers decoupled and ensuring code maintainability.
Unlike ramiramulu, I would refrain from introducing too many abstractions.
If you use EF, your DAL is actually Entity Framework, no need to abstract that. A lot of people attempts to do this but this only complicates your code a lot, for no gain. If you were doing SQL requests and calling stored procedures directly, then a DAL would be helpful, but building an abstraction on top of EF (which is another abstraction, or over NHibernate) is a bad idea.
Also, pure DTOs as an abstraction are more and more frown upon, but they can be used if you have a middleware and do not directly access the database - for example, a message bus like NServiceBus: messages would be considered DTOs in that case.
Unless you do very simple and pure CRUD (in which case, go ahead, put the logic in controllers - no reason to add complexity for pretty straightforward business), you should move business logic outside of your controllers for sure. For this you have many options, but 2 of the most popular are : a rich domain model with domain driven design or rich business services with service oriented design. They are a lot of ways to do this, but these 2 illustrates very different approaches.
Rich Domain (Controller per Aggregate)
In the first case, your controller would be responsible for acquiring the domain object, calling the logic, and returning a View Model. They do the bridge between the View world and the Model world. How to acquire the domain object(s) needs to be somewhat abstracted, often simple virtual methods works great - keep it simple.
Aggregate Root:
public class Item
{
public string itemId { get; set; }
public string itemDescription { get; set; }
public float unitPrice { get; set; }
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
// Example of logic, should always be in your aggregate and not in ItemProductLine for example
public void UpdatePrice(float newPrice)
{
// ... Implement logic
}
}
View Model:
public class ItemViewModel
{
public int id { get; set; }
public string itemNumber { get; set; }
public String itemDescription { get; set; }
public Double unitPrice { get; set; }
public string productLine { get; set; }
}
Controller:
public class ItemController : Controller
{
[HttpGet]
public ActionResult Edit(int id)
{
var item = GetById(id);
// Some logic to map to the VM, maybe automapper, valueinjector, etc.
var model = item.MapTo<ItemViewModel>();
return View(model);
}
[HttpPost]
public ActionResult Update(int id, ItemViewModel model)
{
// Do some validation
if (!model.IsValid)
{
View("Edit", model); // return edit view
}
var item = GetById(model.id);
// Execute logic
item.UpdatePrice(model.unitPrice);
// ... maybe more logic calls
Save(item);
return RedirectToAction("Edit");
}
public virtual Item GetById(int id)
{
return dbContext.Items.Find(id);
}
public virtual bool Save(Item item)
{
// probably could/should be abstracted in a Unit of Work
dbContext.Items.Update(item);
dbContext.Save();
}
}
This works great with logic that trickles down and are very model specific. It is also great when you do not use CRUD and are very action-based (e.g. a button to update only the price compared to an edit page where you can change all item values). It is pretty decoupled and the separation of concerns is there - you can edit and test business logic on their own, you can test controllers without a backend (by overriding the virtual functions), and you do not have hundreds of abstractions built on one another. You might roll out the virtual function in a repository class, but by experience you always have very specific filters and concerns that are controller/view dependent, and often you end up with one controller per aggregate root, so controllers are a good place for them (e.g. .GetAllItemsWithAPriceGreaterThan(10.0))
In an architecture like that, you have to be careful about boundaries. For example, you could have a Product controller/aggregate and want to list all Items related to that product, but it should be read-only - you couldn't call any business on Items from Products - you need to navigate to the Item controller for that. The best way to do this is to automatically map to the ViewModel :
public class ProductController : Controller
{
// ...
public virtual IEnumerable<ItemViewModel> GetItemsByProductId(int id)
{
return dbContext.Items
.Where(x => ...)
.Select(x => x.MapTo<ItemViewModel>())
.ToList();
// No risks of editing Items
}
}
Rich Services (Controller per Service)
With rich services, you build a more service oriented abstraction. This is great when business logic spawns multiple boundaries and models. Services play the role of the bridge between the View and the Model. They should NEVER expose the underlying Models, only specific ViewModels (which play the role of DTO in that case). This is very good when you have a MVC site and some REST WebApi working on the same dataset for example, they can reuse the same services.
Model:
public class Item
{
public string itemId { get; set; }
public string itemDescription { get; set; }
public float unitPrice { get; set; }
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
}
View Model:
public class ItemViewModel
{
public int id { get; set; }
public string itemNumber { get; set; }
public String itemDescription { get; set; }
public Double unitPrice { get; set; }
public string productLine { get; set; }
}
Service:
public class ItemService
{
public ItemViewModel Load(int id)
{
return dbContext.Items.Find(id).MapTo<ItemViewModel>();
}
public bool Update(ItemViewModel model)
{
var item = dbContext.Items.Find(model.id);
// update item with model and check rules/validate
// ...
if (valid)
{
dbContext.Items.Update(item);
dbContext.Save();
return true;
}
return false;
}
}
Controller:
public class ItemController : Controller
{
public ItemService Service { get; private set; }
public ItemController(ItemService service)
{
this.Service = service;
}
[HttpGet]
public ActionResult Edit(int id)
{
return View(Service.Load(id));
}
[HttpPost]
public ActionResult Update(int id, ItemViewModel model)
{
// Do some validation and update
if (!model.IsValid || !Service.Update(model))
{
View("Edit", model); // return edit view
}
return RedirectToAction("Edit");
}
}
Controllers are only there to call the Service(s) and compose the results for the Views. They are "dumb" compared to domain oriented controllers, but if you have a lot of views complexities (tons of composed views, ajax, complex validation, json/xml processing along side html, etc.), this is the preferred approach.
Also, in this case, services do not have to related to only one model. The same service could manipulate multiple model types if they share business logic. So an OrderService could access the inventory and make adjustments there, etc. They are more process-based than model-based.
I would do it this way -
My Domain Model -
public class Item
{
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
}
public class ItemProductLine : ProductLine
{
// more fields
}
public class ProductLine
{
// more fields
}
DAL Would be -
public class ItemRepository
{
public Item Fetch(int id)
{
// Get Data from Database into Item Model
}
}
BAL would be -
public class ItemBusinessLayer
{
public Item GetItem(int id)
{
// Do business logic here
DAL.Fetch(10);
}
}
Controller would be -
public class ItemController : Controller
{
public ActionResult Index(int id)
{
Item _item = BAL.GetItem(10);
ItemViewModel _itemViewModel = AutomapperExt.Convert(_item); // something where automapper will be invoked for conversion process
return View(_itemViewModel);
}
}
Automapper will be maintained in a separate class library.
The main reason why I choose this way is that, for a particular business there can be any number of applications/frontends, but their business domain models shouldn't change. So my BAL is not going to change. It returns business domains itself. Thats doesn't mean everytime I need to return Item model, instead I will have MainItemModel, MiniItemModel etc., all these models will server business requirements.
Now it is the responsibility of frontend (probably controllers) to decide which BAL method to be invoked and how much data to be used on frontend.
Now some devs might argue, that UI shouldn't be having that judgement capacity to decide how much data to use and what data to see, instead BAL should have that power to make decision. I agree and that happens in BAL itself if our domain model is strong and flexible. If security is main constraint and domain models are very rugged, then we can have the automapper conversion at BAL itself. Or else simply have it on UI side. End of the day, MVC is all about making code more manageable, cleaner, reusable and comfortable.

ASP.NET MVC N-Tier application with WCF and entity framework efficient loading

I am after some advice on using entity framework in an efficient way with a WCF service called from an MVC application.
I have a ASP.NET MVC web application as the presentation layer that calls through to a WCF service which does all the data manipulation. The WCF application uses entity framework to perform the operations on the DB.
The problem is that depending on the page that is being rendered the information required from the DB will change, for example if I want to show a list of all the users I might just want their username but the WCF service would return the whole model, this obviously becomes very inefficient when working with large numbers of records.
Is there any ways to make this more efficient, need to somehow be able to specify the values for Include and Select in the Linq statements
If i get you right, you're actually saying that your Models are not compatible with the needs of your Views.
That is (one of the reasons) why people are using Data Transfer Objects (DTO) as the objects returned from the data service, and not the entities themselves.
Usually, you will need to project / map your entities into the DTO object.
for example if I want to show a list of all the users I might just
want their username but the WCF service would return the whole model
For this particular scenario you could try something like this:
// Your 'User' Entity
public class User : BaseEntity
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Phone> Phones { get; set; }
}
// Base class for all 'Mappable' DTOs
public abstract class Mappable<ENTITY, DTO> where ENTITY : BaseEntity
{
public abstract DTO ToDTO(ENTITY entity);
}
// Your DTO (specific to your grid needs)
public class UsersGridDTO : Mappable<User, UsersGridDTO>
{
public int Id { get; set; }
public string Username { get; set; }
public override UsersGridDTO ToDTO(User entity)
{
return new UsersGridDTO
{
Id = entity.Id,
Username = entity.Username
};
}
}
// In your WCF data service
public IEnumerable<DTO> GetData<DTO>() where DTO : Mappable<Entity, DTO>, new()
{
return efContext.Users.Select(new DTO().ToDTO);
}
Also, When using Asp.Net MVC, the DTOs can be used as your ViewModels as well (see here).
You can also use frameworks like AutoMapper that can handle the Entity to DTO mapping for you.

ASP.NET MVC view model best practices

My ASP.NET MVC site connects to a WCF service to get data. The WCF service returns a data contract like this:
[DataContract]
public class Person
{
[DataMember]
public string First { get; set; }
[DataMember]
public string Last { get; set; }
}
The view model in my MVC project looks like this:
public class MyViewModel
{
public string SomeExtraField1 { get; set; }
public string SomeExtraField2 { get; set; }
public string SomeExtraField3 { get; set; }
public Person Person { set; set; }
}
Should my view model be referencing the "Person" data contract that is returned from the data service? Or should I create a new "Person" class in my MVC project that mirrors the properties on the "Person" data contract?
The WCF service call is hidden behind an interface. It seems to be that having the interface reference the data contract makes my interface a leaky abstraction. However, I have a few people that believe creating an additional "Person" class in my MVC project that mirrors the data contract is code bloat.
What are are the best practices surrounding this type of layering/decoupling?
Should my view model be referencing the "Person" data contract that is returned from the data service?
No, avoid this, it's giving developers the false impression that they are using view models. I quite often see code like this when doing code reviews:
public class MyViewModel
{
public SomeDomainModel1 Model1 { get; set; }
public SomeDomainModel2 Model2 { get; set; }
...
}
and that's just wrong. When I critique them for not using view models they show me this and tell me: "Darin, look, I am using view models", unfortunately that's not how view models are supposed to work. They are not wrappers around domain models.
Or should I create a new "Person" class in my MVC project that mirrors the properties on the "Person" data contract?
Yes, you could create a PersonViewModel and include only the properties that your view needs of course.
Or if the particular view you are designing this view model for needs only some properties you could also make it look like this:
public class MyViewModel
{
public string SomeExtraField1 { get; set; }
public string SomeExtraField2 { get; set; }
public string SomeExtraField3 { get; set; }
// this would be for example the concatenation of your domain model
// first name and last name as that's what this particular view needs to
// display
public string PersonFullName { set; set; }
}
As far as the conversion between your domain models and view models is concerned, AutoMapper is simply put: excellent.
I'd say create a Mapper layer that would convert between the WCF Person class and the "mirror" Person class. That way you are tying your MVC implementation to a POCO and not directly to WCF. This adds the ability to swap out WCF with another service without touching MyViewModel in the future if need be (looser coupling).

managing lookup in MVC2 and persisting object with Nhibernate

My simplified domain model looks something like this:
public abstract class Entity<IdK>
{
public virtual IdK Code { get; protected set; }
}
public class Contact : Entity
{
public virtual string Name { get; set; }
public virtual Company Company { get; set; }
}
public class Company : Entity
{
public virtual string Name { get; set; }
}
and I've defined a viewmodel:
public ContactViewModel()
{
public Guid Code { get; set; }
public int Version { get; set; }
public string Name { get; set; }
public string Company { get; set; }
public List<SelectListItem> Companies { get; set; }
}
to manage my contacts in a view.
Since I want the user to be able to choose from a list of companies I've added a list of SelectedListItem which will be rendered in my view like this:
<%=Html.ListBoxFor(m => m.Company, (List<System.Web.Mvc.SelectListItem>)Model.Companies)%>
Now, when the user submits my form I remap my viewmodel with my model before I save it.
I populate my Contact and use the id of the ContactViewModel.Company to create an object of type Company to associate with the property of the Contact class.
Since I don't want to fetch the whole company from the database I just fill the id.
When I persist my contact, though, I get an exception: "not-null property references a null or transient Domain.Contact.Company".
What is the best solution to manage lookups and persistence with MVC + Nhibernate?
Do you have any suggestions from your experience?
Unfortunately with NHibernate and lookups you can't just assign the ID property to a new instance of the Company object and then assign that Company object to the Contact.
Generally what I would do is in my repository, assuming that you can't change the Company information when saving a contact is something like this:
public Contact Save(Contact contact)
{
if(contact.Company.Id > 0)
contact.Company = Session.Load<Company>(contact.Company.Id);
Session.SaveOrUpdate(contact);
}
I generally find this allows you to encapsulate the logic of loading the Company and also allows you to keep it all wrapped up nicely in a single session.
Using Session.Load in this manner avoids hitting the database as described here
If you don't do this, what you're essentially saying to NHibernate is that you have a company object which you have assigned an ID and now want to save it with all the properties set to Null or empty string values or whatever and that is not what you want.
Alternatively you could create a Save specific Domain Object that looks like this:
public abstract class Entity<IdK>
{
public virtual IdK Code { get; protected set; }
}
public class SavableContact : Entity
{
public virtual string Name { get; set; }
public virtual IdK CompanyId { get; set; }
}
Which maps directly to the Contact table in your database so that when you Save this entity you can literally just map back the CompanyId from your view model and NHibernate will only save that value back and not care at all about the company objects.
It's a case of working out what works best for you. I personally prefer the first option as the extra bit of logic helps simplify the domain model, however if you're creating and exposing a public API then the second method might make more sense.

Validate a model in viewmodel?

I wonder if there is a way to validate just one of my models in the viewmodel send it to my action? I use the DataAnnotations as validate rules.
Like the if (!ModelState.IsValid)
let me know if the question is unclear and I will edit for a better explination
EDIT
my viewmodel looks like this
public class CompaniesViewModel
{
public Core.Model.Customer Company { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
public Core.Model.Meeting Meeting { get; set; }
}
What I want to do in this particular situation is to validate just Customer. I cant do the ModelState.IsValid then all get validated. So how can I do to just validate one of them like customer in this case. Hope this was more clear
There are a number of different ways you can do this. The first is to add a property called IsValid that checks the property. So something like:
public class Company
{
public bool IsValid
{
get { return GetValid() }
}
private bool IsValid()
{
if ( Some check here )
return false;
}
}
[HttpPost]
public ActionResult SomeAction(CompaniesViewModel model)
{
if (model.Company.IsValid)
{
}
}
However a better solution IMO would be just to post the Company to your controller rather than your entire view model. Just because your passing a view model to a view it doesn't mean that you need to post the entire view model back. When you create your HTML form specify only the properties you want to post back to your controller. So for example your controller would become:
[HttpPost]
public ActionResult SomeAction(Company company)
{
if (Model.IsValid)
{
}
}
Now when you check if Model.IsValid it just check company as that is all you've passed back to the controller.
At server side, you can try the ValidateModel(object) method, like in TryValidateModel(CompaniesViewModel.Company).
If you have enabled client sided validation, you need to post only the relevant entity. If you want to post all entities, but you need to validate only one, you can consider the following:
either removing the rules, using javascript ASP .NET MVC Disable Client Side Validation at Per-Field Level
or creating a Data-Transfer-Object, ie a View Model which has NO link to the Model, but reproduces the entities you want with the validation rules you want having applied in this scenario. Of course, then, you'll need in your controller or a model binder some way to bind from your ViewModel to your Model entities.
You can separate Customer Model to another class in your ViewModel and map that in Controller to a existing/new Customer:
public class CompaniesViewModel
{
public Company Company { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
public Core.Model.Meeting Meeting { get; set; }
}
//Validations for Company go here:
public class Company
{
public string CompanyId { get; set; }
[Required]
public string CompanyName { get; set; }
}

Resources