MVC 3 Code First ViewModel - How to? - asp.net-mvc

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.

Related

How to design EF core code-first database when different tables share the same fields

I'm working on a ASP .NET Core 5 MVC application with MS-SQL database and EF Core is my ORM (with the code-first approach).
Currently I'm redesigning the database, I have multiple tables that share a lot of the same properties, and I want to be able to add/remove properties from different tables, but only in one place in the code.
Because .NET doesn't have multiple class inheritance, I came up with the idea to inherit the classes in "levels".
Basically, in the example below, the purchases table and the products table should have exactly the same prices, dates and content properies, but also some additional specific fields:
class Purchase : PriceDatesAndContent
{
// specific purchase properties
}
class Product : PriceDatesAndContent
{
// specific product properties
}
class PricesDatesAndContent : PriceAndDates
{
public string Name { get; set ; }
public string Description { get; set; }
}
class PricesAndDates : Prices
{
public DateTime someDate1 { get; set; }
public DateTime someDate2 { get; set; }
// ...
}
class Prices
{
public double Price1 { get; set; }
public double Price2 { get; set; }
}
However, I'm not really sure that this is really a brilliant idea as it seems to me, I would love to hear your opinion, or maybe you even have another workaround for this scenario?
Thank you very much!
However, I'm not really sure that this is really a brilliant idea as it seems to me
Having a deep inheritance hierarchy is fine so long as your base classes aren't mapped as Entities. But it is unusual to model your classes this way just to save yourself a bit of typing.
It would probably be better to use interfaces to model the common property patterns, so you don't have to arrange them in a single hierarchy. eg
public interface IHasName
{
public string Name { get; set; }
public string Description { get; set; }
}
public interface IHasPrices
{
public double Price1 { get; set; }
public double Price2 { get; set; }
}

building view using a generic interface

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.

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.

combine 2 related model in mvc

I have 2 models like this.
public partial class Question
{
public int QuestionId { get; set; }
public string QuestionText { get; set; }
public string Ans1 { get; set; }
public string Ans2 { get; set; }
public string Ans3 { get; set; }
public string Ans4 { get; set; }
}
public partial class UserAnswer
{
public int UserAnsId { get; set; }
public Nullable<int> QuestionId { get; set; }
public Nullable<int> UserId { get; set; }
public Nullable<int> AnsVal { get; set; }
}
As you can see QuestionId is in both the models. How can I render it in view. There are multiple questions. Question Moldel has data in initial run but UserAnswer doesn't.
How can I combine these 2 models so that I can use it as IEnumerable in view. Ans1,Ans2,Ans3,Ans4 has text and AnsVal in UserAnswer will get its value from Raiobutton.
make a combine class like below..i am not sure this is perfect or not..any suggestions are acceptable.
public class QuestionAnswerViewModel
{
public Question Question {get;set;}
public ICollection<UserAnswer> Answers {get;set;}
}
You want to create a ViewModel that represents the combined model objects. This keeps things clean, your model is just that, the model, what gets passed to the view can be the model but in many cases the concept of a ViewModel will make things easier to design while keeping your code loosely coupled and clean. This also keeps things that are not important to the View out of the equation aka particular properties in your model such as maybe a CreatedDate should not be passed to the View, especially since View requests will pass back the value as null since it is not being used in the view and thus not populated on postback. This could lead to you updating the database with a null value for CreatedDate simply because it was not used in the View.
Maybe you have a Model class library in your solution? If you do, create another class library called MyNamespace.Web.ViewModels or something like that. Also you should look into using a tool like AutoMapper that will populate the ViewModel on View request to the Controller and populate the model on View postback to the controller.

Confusion between DAL, Service Layer and repositories

Say I have a simple model like these (small part of a pretty large app)
public class EHR : IEntity
{
public int ID { get; set; }
public string UserName { get; set; }
public DateTime CreationDate { get; set; }
public virtual ICollection<PhysicalTest> PhysicalTests { get; set; }
}
public class PhysicalTest : IEntity
{
public int ID { get; set; }
public virtual EHR Ehr { get; set; }
public Boolean IsDeleted { get; set; }
}
And i want for an easy way to get the physicalTests that are NOT deleted for a given EHR.
So, I can think of three ways of doing this.
one is simply adding a method to my EHR class.(it doesnt seem as such a bad idea cause I dont want to suffer from anemic domain model)
public IEnumerable<PhysicalTest> ActivePhysicalTests()
{
return this.PhysicalTests.Where(!m=>m.IsDeleted).ToList();
}
the other one is creating an extension method under a EHRRepositoryExtensions class:
public static class EHRRepositoryExtensions
{
public static IEnumerable<PhysicalTest> Active(this IEnumerable<PhysicalTest> physicalTests)
{
return physicalTests.Where(test => !test.IsDeleted).OrderByDescending(test => test.CreationDate).ToList();
}
}
I also think I could have extended my IRepository to include a method that returns only the physsicalTests that arent deleted.
something like
public class EHRRepository : IRepository<EHR>
{
//TODO: method that returns only the physsicalTests that arent deleted.
}
I am still trying to grasp many concepts on DDD and I want it to be as pure as possible.
Which of this approaches would you recommend?
whats a rule of thumb on topics like this?
Please Help.
The first approach is recommended as EHR is your Aggregate Root and it is the information expert about its physical tests.
Second approach is not relevant as you have already the model and you can add this method to the entity instead.
The third approach would be preferable only if the list of physical tests takes much time to load from the database, still you can utilize lazy loading but if you want to separate the fetching from the domain or you dont use a lazy loading enabled ORM then put it as a query method in the repository

Resources