Strongly typed Views using ViewModels - c#

I'm using Entity Framework 5 with MVC 4. I used the DbContext Fluent API to create POCO entities.
Let's say that in a specific View, I need access to two or more entities.
What I typically do is create new folder called ViewModels and create a superclass. Then, I simply copy the POCO entities into this superclass to use it in my View.
However, I was trying to think of a way to take advantage of the scaffolding when adding a Controller & View for the superclass inside that ViewModels folder because now, that folder is not part of the EDMX ORM model which the Model Class (in the window) tries to access and put in the list when the Scaffolding option is set to "MVC Controller with read/write actions and views using Entity Framework".
Obviously, many times you'll need a composite of entities to work with in a View rather than just one.
Is there a way to do this, or is the CRUD simply set up only for one entity per View?

Related

Can DTO in MVC asp.net load data by itself

Consider that I have DTO for view. At domain layer we have the entity . We can use automapper to fill the DTO from entity. But do we need to perform all these at application service class or can we have method at Model which can be called by Controller to perform this process. I need to know the class structure for MVC
Regarding adding the mapping methods to Models, I would disagree and suggest to keep the Entity classes as simple as possible (POCO). I personally prefer to do the mapping either at Application Service Layer or in ViewModels.

Entities cannot be tracked by more than one context, interferes with N-tier design

I have a colleague who insists I develop ASP.Net MVC websites using an n tier data access layer and MVVM.
He has a background in Silverlight and WPF and I have attempted to create a solution but it is causing problems.
I created and DAL and logic layers (using generics):
Dal - containing a repository pattern that wraps up entity frame work.
Logic - pass through layer, no generic logic to apply currently.
I am still using the MVC pattern and am passing the Entity framework model to View unless the need additional properties or methods - in which case I create a view model and an interface to map between the two.
The n tier data access layer has locked the entity framework context at the bottom of the stack and the main problem I have that entities can't be tracked on more than one context. ({"An entity object cannot be referenced by multiple instances of IEntityChangeTracker."})
I recently came across a problem where context coming up with this error despite my attempts despite to use models, interfaces, deep copying.
The issue here is this was the approach I was going to take to try and put a model in the DAL layer and map the data between entity framework entity and model.
I understand the underlying issue: that even though you dispose of a context it doesn't release the entities that were attached to it. Is there anyway to get this n tire data access approach to work with MVC? or am right this will never work and I should stick to using the entity framework context in the controller method (or underlying class implemented using dependency injection).
There's a lot to unpack here.
If you are looking for an MVVM implementation, then you are going to want to look at something like knockout.js. Or some other framework that is going to do declarative databinding in the client side. there are a number of articles that you can read to understand this.
https://learn.microsoft.com/en-us/aspnet/core/client-side/knockout
but let's start with the assumption that you aren't going down that road and want to stick with MVC.
I would stop passing entities to your views. You are going to cause yourself endless grief. Create a view model for each corresponding view. you use of an interface seems like overkill. You can project linq queries for your entities/repos right into the the view models. you could also use something like Automapper to map from entity to view model. Appending some of your code to the questions might help. And my view models tend to be pretty flat. I don't see why you would need to perform deep copies of entity trees out to the view. Those can be gotten latter using partial views or some other method.
Now that you aren't sending entities out to the view, when you post information for updating, you are going to have to instatiate a new object for fetch the object you are looking to update from ef again. make your changes and save.
To me that simplest implementation is the best. I would pass you context to the controller method (preferably using an IoC) and querying the context directy in the controller action and projecting directly into the view model. If you've got a lot of shared code between controller actions, maybe move stuff into a service and then inject the service into the controller and inject the context into the service. but i'd start with just injecting the context into the controller.

Layer ASP.NET MVC Project

I am trying to understand the concepts of a good designed project.
I am using ASP.NET MVC and i am trying to create a layered (pluggable) project.
The current project structure what i have now is this:
LayeredProject - the MVC Project containing Controllers
LayeredProject.EntityFramework - contains all the POCO classes used for database. (i am using Code First approach)
LayeredProject.Model - this should contain all the business objects used in the project.
Saying that the project is a eCommerce website, i would structure it like this:
In the LayeredProject.EntityFramework project i have classes which corresponds to the database tables. Category, Product, User. This project is used only for saving and loading data from database, and those objects should not be used for other purposes. This project has a reference to LayeredProject.Model project.
In LayeredProject.Model project i store all the objects i work with, which most of them are exactly copies of LayeredProject.EntityFramework POCO's objsects and some other Services Classes used.
In LayeredProject i keep all my ViewModels classes, Controllers, and different UI logic. This project has a reference to LayeredProject.Model project.
First of all, i am not sure that this is the right way of doing this.
And, it this is the right way of doing it, then i get a little confused because i will have a duplicate of my POCO classes in EntityFramework project and also on Model project.
Please help me understanding this
You can Design Your Project using layered structure as well using MVC. The Controller and view part should stay intact. You can divide the business logic part as many layers as you want. The model should come as a result of the number of layers you are expecting. For this keep your business logic in a separate project (not neccessary: it can be there in web project itself), refer the dlls from that project to the MVC web solution. Pass the models which are generated as a result of database querying to the web solution and with the help of controller render the view.(I have done my project using this style)
The MVC project should contain:
view models: models for the views, i.e. models that are very specific to render each view (these model are not the M in MVC). This models usually contain the data which must be shown or edited in the view, as well as aditional necessary information to render the view: for example, if the view must render Drop Down Lists, the view model should contain the corresponding SelectList or IEnumerable to populate the list. You can use mappers, like AutoMapper or ValueInjecter to move data from the business entities (entities coming from the Business Layer) to the view models, and viceversa. Or if appropriate, you can use directly the business entities as properties in the model view (the view model doesn't need to be flat: it can contain objects as properties)
views, strongly typed with the view models
controllers: this controllers use the Business Logic (that is the Model, the M in MVC) to control the application flow, to create and provide the model views for the views, and to react to the user actions
UI helper: I usually add this layer to fulfill the DRY principle. I.e. if I have to prepare a SelectList and it's going to be used in many views, I do it in this layer, and use it from all the necessary places. This can include calculations, orderings, or anything tighly related to the UI, so it doesn't fit in the Business Layer (Model). This uses the Business Layer, and provides data specific for the Views.
Those are the specific and critical parts of MVC, which includes the VC in MVC (views and controllers) The M in MVC (Model) is the business logic which can be done 'as usual'. I.e. you don't have to do anything special in your business layer to use it with MVC. You can use the technology of your choice (a traditional DAL + BLL, WCF, WS, or whatever you want).
This is something which works well for LOB applications. Of course, if you're making a toy application, you can forget this all and make something more monolythic. But I only recommedn this for very little applications with scarce maintenance needs.
These are examples of objects in several layers that allow to edit a "Pet":
Business Logic Layer:
PetService, a class which can be use to read, write, find, and modify pets (as explained above it doesn't matter how this is implemented)
Business Entity: it's the BLL entity for managing Pets. This could be a POCO object or a DDD entity:
Pet - int Id, int PetTypeId, string Name...
View Model: contains a Pet proerty, as well as a list of PetTypes, so that the view can render a drop down list for the PetTypeId:
PetViewModel - Pet ThePet, SelectList PetTypes
UI Helper: if the PetTypes is going to be used in more than one or two views, a PetUiHelper could provide this select list for all the views that require it:
PetUiHelper - GetPetTypesList()
Pet views: a strongly typed view for PetViewModel
Views\Pet\Edit.cshtml
PetController: uses the PetService to create the views, and their model views.
PetController - Edit(int id) --> returns an Edit view, woth its corresponding PetViewModel. There must be also an HttpPost Edit action which receives the user input in an specific model or the PetViewModel, or the Pet plus the Id or whatever. This depends on what you're editing.
Finally, if you know how to use DI, you can use Unity.Mvc or any of the other options to inject the Business Services in the controllers.
seems your using the Code First approach to build a data access, you can dig in this extensive article and gain more insight.
http://ofps.oreilly.com/titles/9781449320317/ch_AdvancedData.html
You probably have one too many layers in there, there should be no reason to separate the model with the business logic from the LayeredProject MVC layer itself unless you are planning to have a client app or some other separate project to access the model. In the MVC project you already have a model folder that can be used for that. However in the MVC project you should also add a "ViewModels" folder to keep models that are specifically used for the view concerns (e.g. DTO objects).
This project shows a nice simple way of keeping the things separate simply within folders in the MVC project: RacoonBlog Project. Although it uses RavenDB rather than EF the ideas are the same.
Most MVC apps I have worked were layered in this way
MVC Project: Had the controllers, views and models. The business logic resides in the model.
The Data Access layer (Persistence layer) : This project uses an ORM. (In your case entity frame work)
Classes that are mapped to the database tables reside in the Model and not the data access layer.

Using MVC3 With DBML

Right now I am using classes generated in the .dbml file and passing the data to the controller through an implementation of the repository pattern. My question is this, do I need to create classes that are essentially clones of the classes from the .dbml without the linq-to-sql and without certain flags, or the ID to have the proper separation of domain logic?
The clones you are referring to have a name: view models. And yes, you absolutely should be using view models. They are tailored to the specific requirements of a given view. The controller should then query the repository in order to fetch some domain models (autogenerated Linq-To-Sql class, EF entities, ...) and map them to a view model class which will be passed to the view. That's how IMHO every properly architected ASP.NET MVC application should be designed. You should not pass domain models to a view, nor receive any domain models as action parameters from a view. Only view models.
View models are not clones of a domain model. A view model could be mapped out from multiple domain models, or one domain model might break into multiple view models. This way the views have the full flexibility to represent the data independently of the way this data has been transported in the business layers.

asp net mvc validation and ViewModel

I have four layer solution a medium size project:
Model (EF POCO entities)
Data (EF ObjectContext)
Services
asp net MVC question
a)Should i have validation attributes- Dataanotation in Models or MVC project?
b)where should i set ViewModel-s if in MVC then where do i fill ViewModels with data, in Controller? else if on other project should create Repository for VewModel?
c) should ViewModel have validation>?
A, C) If you have view models that are different from your DTOs, then you might prefer to use DataAnnotations in both types. This way, you can validate before you try to persist and again as you persist in case your DTOs are used outside the scope of your MVC app.
B) I usually tuck my view models into the Models folder of my MVC app and my DTOs into a data project that is separate from my MVC app. I use AutoMapper a LOT to copy values between my view models and my DTOs.
It's okay to have validation on Models and ViewModels. It's on you what you like more, but it's better to have validation on ViewModels (you don't need to use binding and so), but there is more work with creating lot's of ViewModels when Models can be used too.
I really prefer to create two folder inside the models:
One is for Database model class and another is for view models.
You can also add all type of validation into the database model class.

Categories