I am working on an ASP.Net MVC Website.
I have a table called animal, which is created based of this class using Entity Framework code first:
public class Animal
{
public int AnimalId { get; set; }
public string AnimalName { get; set; }
public int NoOfLegs { get; set; }
public int FlyingSpeed { get; set; }
public int RunningSpeed { get; set; }
}
Now I have my AnimalRepository that reads this info from the DB and pass it to my ViewModel (My Domain Classes are different from my ViewModel and I am using ModelReader, ModelWriter and AutoMapper to Map my domain model into my view model as explained here). I have this generic interface in my ViewModel:
public interface IAnimalModel
{
int AnimalId { get; set; }
string AnimalName { get; set; }
int NoOfLegs { get; set; }
}
And I have these two classes in my ViewModel:
public class DogModel: IAnimalModel
{
public int AnimalId { get; set; }
public string AnimalName { get; set; }
public NoOfLegs { get; set; }
public int RunningSpeed { get; set; }
}
public class EagleModel: IAnimalModel
{
public int AnimalId { get; set; }
public string AnimalName { get; set; }
public NoOfLegs { get; set; }
public int FlyingSpeed { get; set; }
}
Now I have one Animal Controller that uses AnimalRepositoy to get the data from DB, and maps it to the correct ViewModel.
I want to bind my View to IAnimalModel interface so that I can pass different animals to the same View.
In my View, I want to use Razor Code to display certain properties based on Animal Model type, something like this:
#if (typeof(Model) == typeof(EagleModel)) {
Html.EditorFor(model => model.FlyingSpeed)
}
#if (typeof(Model) == typeof(DogModel)) {
Html.EditorFor(model => model.RunningSpeed)
}
I have been thinking about this for a long time and I am not sure if this is a good solution? I have quite a few different Animal types with a lot of common properties, so don't really like the idea of creating one Table for each different animal.
I thought it's better to map them to correct type in my ViewModel...
I am not really sure if binding my ViewModel to IAnimalModel interface is a good idea? As I need to check the model type before displaying certain properties.
Another disadvantage is that in my DB, I don't know which type of animal each row contains... I am thinking maybe of I have to add a ViewModelType column to my Animal table, but again I am not sure if this is a good solution?
I think the problem is much simpler to be honest.
You're talking about a lot of animals but you could think in terms of types and then everything simplifies.
So based on some very quick research, you have 6 animal types:
Invertebrates
Fish
Amphibians
Reptiles
Birds
Mammals
You can probably get away with less. So if you look at your problem from this point of view, now you don't have that many different types to look at.
So, have an animal type enum and use that to differentiate the fields you are displaying.
In terms of database, I would not go with one table and null fields as that complicates everything. Either create a base one with whatever is common and a separate one for each type, or go with a Nosql db and save one type data per row.
Finally I don't really think that using a base interface gives you anything. You still have to repeat the fields in every class that implements it and you're not achieving anything in terms of simplification. If you instead go with a base abstract class then at least you don't have to repeat the same properties everywhere and your classes are now smaller and reflect the differences properly.
I've googled some around the internet and found some articles about the subject, but none of them satisfied me. I want to know is it good to use object-object mapper to map objects to each other? I know it depends on situation to use, but how will I realize a good or best situation to use?
Taking a step back, it's best practice to separate data transfer objects (DTOs) and view models (VMs) from business objects (entities and alike). Mapping libraries, in that regard, are a means to an end and simply make that association easier.
As far as when, that's up to you. If you feel like you can convert between your business models and DTO/VMs in a way that's easy to maintain, go ahead. From my personal experience, that only goes so far (especially as the requirements change). Therefore, I'm fond of mapping libraries (specifically AutoMapper as I've come to know it's API and am comfortable plugging it in).
Having said that, any time I have to go between these two models I use AutoMapper. I simply configure it once and I'm off and running. Additional tweaks to the models (on either side) then become easier as I can change those bindings in one place (map definition file) and methods automatically "catch up".
Example:
My database contains a Record for a product:
class Product
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int QuantityOnHand { get; set; }
public int? ReorderQuantity { get; set; }
public string Sku { get; set; }
}
I may present this to the UI in a more distilled format:
public class ProductViewModel
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int Quantity { get; set; }
}
If this came from a repository of some kind, I'm simply calling:
var model = Mapper.Map<ProductViewModel>(productFromRepository)
Here I consistently get the view model I care about from the Product I've requested. If the business/service layer were to add/change/remove properties, I'd only go back to my Mapper.CreateMap<Product, ProductViewModel>() defintion, but the rest of my presentation logic would remain in-tact.
In addition to #Brad Christie's answer, automapping types which have minor differences into a single overarching type is generally easier if you are meaning to display them on your view alongside other products that are generated different ways.
If you'll allow me to crib off one my own previous answers, here's an example:
class SingleProduct {
string Name {get;set;}
decimal Price {get;set;}
decimal GetActualPrice() { return Price; }
}
class ComboSaleProduct {
string Name {get;set;}
List<SingleProduct> ComboProducts {get;set;}
decimal GetActualPrice() { return ComboProducts.Sum(p => p.GetActualPrice()); }
}
class ProductViewModel {
string Name {get;set;}
decimal ActualPrice {get;set;}
}
Automapper wires everything together so that you can return either of these and it will automatically map the "GetActualPrice" to ActualPrice on your viewmodel.
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.
I'm currently playing around with ASP .NET MVC 3 and - for data access - the code first approach of the Entity Framework.
I've read a lot of documentation, blogs, stackoverflow questions etc. but haven't found a precise answer to the following question and I hope someone out there can help me.
I have a simple (database) model containing two entites: Project and Customer
public class Project
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Customer Customer { get; set; }
}
and...
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public int Rate { get; set; }
}
For displaying - for example - a list of the customers I have created a simple ViewModel:
public class ProjectListModel
{
public List<Project> Projects { get; set; }
}
The code in my controller is:
public ActionResult ProjectList()
{
var model = new ProjectListModel()
{
Projects = db.Projects.OrderBy(x => x.Customer.Id).ToList<Project>()
};
return PartialView("_ProjectList", model);
}
So I can display the list of the projects and even the corresponding customer name.
#Html.DisplayFor(modelItem => item.Name), #Html.DisplayFor(modelItem => item.Customer.Name))
And here starts my question ;-)
I'm unsure if I understood the concept of ViewModels correctly as I'm returning a list of my "database objects". How would you do that? I could imagine a new class:
public class SingleProjectForViewModel
{
public string ProjectName {get;set;}
public string CustomerName { get;set;}
}
and change my ViewModel to:
public class ProjectListModel
{
public List<SingleProjectForViewModel> {get;set;}
}
...but then the code in my controller would become very long just to fill the ViewModel (fetch from DB, create instance of SingleProjectForViewModel and add this instance to an instantiated List) - for this example that would be OK but with bigger data classes and more complex views...!?
I also read about Auto-Mapper but I'm unsure if it's "right" to use this tool for that kind of "problem".
Thank you very much for reading this - and much more for answering or any advice! :-)
You understand View Models correctly. They are intended to remove the View layer from having ANY coupling to the data layer.
You could/should break your data access code into helper classes and methods, to remove the complexity from your controllers. These methods would query the data layer and return the view model.
I haven't used automapper, but it sounds like something that could definitely help here.
Here's a sample of how it works now:
[MetadataType(typeof(PersonMetadata))]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class PersonMetadata
{
[Required]
public string Name { get; set; }
[Range(0,150]
public int Age { get; set; }
}
However I don't want the MetadataAttribute to be put on the Person class, instead I want some way of telling the MVC framework "hey if you encounter Person class the metadate is in the PersonMetadata class".
It's just reversing the direction which for me feels more compositional and following the Open-Close Principle since I don't have to touch the Person class to "extend" it with metadata.
I know this creates a problem of possible multiple and conflicting metadatas being attached, also increases complexity but flexibility always comes at a price.
I want either a programmatic or declarative way or preferably both :)
So one could be something like :
MetadataTypeMappings.Add(typeof(Person), typeof(PersonMetadata));
Another could be:
[MetadataFor(typeof(Person)]
public class PersonMetadata
{
[Required]
public string Name { get; set; }
[Range(0,150]
public int Age { get; set; }
}
I'm using MvcExtensions. One of the features is a nice way to describe metadata like this:
public class ProductEditModelConfiguration :
ModelMetadataConfiguration<ProductEditModel>
{
public ProductEditModelConfiguration()
{
Configure(model => model.Id).Hide();
Configure(model => model.Name)
.DisplayName(() => LocalizedTexts.Name)
.Required(() => LocalizedTexts.NameCannotBeBlank)
.MaximumLength(64, () =>
LocalizedTexts.NameCannotBeMoreThanSixtyFourCharacters);
}
}
Neat thing is - this allows to use resources for localization in strongly typed fashion.
Drawback for using this - there's bunch of other things bundled which You might not want to use.