I am developing a site with MVC 3 and Entity Framework 4.1. I am new to MVC 3 Development with Entity Framework so was hoping for some help with some design decisions. My site only has approx 15 pages that a user can go to. Rather than have controllers for each page - I was going to just have one controller class - (but have models for each page). And in the controller class I will keep my methods for each page in regions so they are easy to expand up. So for example I was going to have a LogOn Method in my SiteController that has RedirectToAction Homepage - and the Hompage() Method will live in my SiteController in the HomePage region.
I already have a Database Designed from a colleague (there are approx 12 or so Tables in the DB) - I have been looking at how Entity Framework will create code from that - however would it be advised to keep this code in a DAL folder and still have my own models for each page? So for example - I have a FileName that will be saved in the Database. On my homepage I want to show that FileName - so is it good practice to have a string FileName on my Homepage Model and then in the HomePage() view method the model.FileName is set from db.context(get filename from db).
Would it be best then to instansiate all the db context at the instanstiation point of my SiteController or just instansiate them in the methods that require them? i.e - if Homepage View needs table 1 and table 2 then new them in the Hompage() method and if another view method needs data from or has to save data to table 3/4 then new them at start of that method?
Use the EF Power tools to reverse engineer your database, that will create the folder structure.
KEEP the one controller per page. Unless those pages are part of a wizard type data entry scenario that really are part of the same process, separate them out into multiple controllers.
Right click, add new controller - use the builtin scaffolding to generate your controller using an entity framework context (make sure you build your application after step 1 above, select your context class in the "Add Controller" dialog). It will generate the views and controller for you. Repeat this for each item you want data entry for.
Your context will be instantiated as part of the controllers that are already created for you - you shouldn't need to do anything else (including dispose -the generated code will dispose it for you as well since the controller is disposed)
First observation when you wrote:
Rather than have controllers for each page - I was going to just have
one controller class
I totally disagree with that. For multiple reasons.
Google a litle about the following topics:
SRP (Single Responsibility Principle) aka SoC (Separation of
Concerns)
IoC (Inversion of Control)
SPot (Single Point of Truth)
LSP (Liskov Substitution Principle)
OCP - Open-Close Principle
Related
I have to gradually replace an ASP.NET Web Forms application with an ASP.NET MVC3 layered application. Let's take into consideration just the Repository layer.
In my new MVC application I have one project for Data (name MVC.Data) and one for Web.
In the MVC.Data I have an edmx file with the EF classes, which models just the DB table (no views), and a Respository class myRepository which provides methods that perform simple queries.
In the old Web Forms application I have a GridView which is filled using as DataSource an SQL database view.
In order to have the same result in my new MVC3 application, I have two options:
1) Create a Service layer (and project MVC.Services), where I have a method that fill a new class myViewClass which contains all the fields of the SQL DB view and give it to the controller.
2) Create a class within the MVC.Data project which is directly filled by its constructor by using LINQ statements directly against the EF classes.
I read about the factory pattern and the 1st solution seems the most appropriate, however many people always suggest not to create a Service Layer if it is not needed. What is the best choice in this case?
Actually building the view model should be done in a mapping layer. Basically your controller action might look like this:
public ActionResult Index()
{
SomeDomainModel model = repository.GetSomeDomainModel();
SomeViewModel vm = Mapper.Map<SomeDomainModel, SomeViewModel>(model);
return View(vm);
}
The view model is defined in the MVC project as it is a class that is specifically designed to meet the requirements of the given view.
The Mapper.Map<TSource, TDest> method I have shown in my answer comes from AutoMapper which I use in my project but you could define any custom mapping layer you like.
The mapping layer must also be part of the MVC project as it must be aware of both your domain models and your view models in order to perform the mapping.
As far as the service layer is concerned, you could use one when you have some complex business operations which could be composed of multiple simple repository calls. But some might argue for the existence of a service layer at all. I think that both approaches have their pros and cons that must be evaluated when designing a system and most importantly take into consideration the specific context and scenario you are designing.
I'm using EF with ViewModel and AutoMapper design strategies for an MVC3 application.
I'm wondering if there is a more efficient way of creating the CRUD pages then what I'm currently doing.
My Current Process Involves:
Create the Entity
Create the ViewModel via copy paste then deleted non-required fields
Add the Entity to the Context list
Create a controller via the Visual Studio 2010 create controller wizard page.
I select a Template of Controller with read write actions and views, using Entity Framework.
I choose my model to be my ViewModel instead of my entity.
I select the appropriate context.
Now the part I part I think can be improved, I have to re-write all the CRUD methods to use AutoMapper and the Entity/ViewModel design pattern changing:
return View(db.BlockedUserViewModels.ToList());
into:
IList<BlockedUser> blockedUsers = db.BlockedUsers.ToList();
IList<BlockedUserViewModel> blockedUserVMs = AutoMapper.Mapper.Map<IList<BlockedUser>, IList<BlockedUserViewModel>>(blockedUsers);
return View(blockedUserVMs);
I have to add the same [Authorize] and roles permissions to each controller CRUD option.
This seems way overkill in workload! I'm hoping there a better solution. (I'm coming from Python/Django where it requires a single line of code to create beautiful strong CRUD pages)
It sounds like you can add a service and inject it into your controller. Then you only have to call
var model = _service.GetBlockedUsers();
each time instead of:
IList<BlockedUser> blockedUsers = db.BlockedUsers.ToList();
IList<BlockedUserViewModel> blockedUserVMs = AutoMapper.Mapper.Map<IList<BlockedUser>, IList<BlockedUserViewModel>>(blockedUsers);
This will keep your controllers light and act as a place to keep your crud logic so you don't have to repeat it everywhere.
Also, you can add the [Authorize] attribute to the controller if it applies to every action in the controller.
It really depends on how painful this is for you, but you can always use the MVC scaffolding stuff found in Nuget and written by Steven Sanderson. Investing some time could help you in the long run, but you have to figure out if it's right for you.
http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/
So I did some Google searching on the MVC pattern and I'm still not exactly sure what the "Model" part is. What exactly does it deal with? I'm rather new to programming so all the explanations I can find go right over my head. I'd really appreciate it if you could give me an explanation in simple terms.
Thanks
The simplest way I can describe it is to call it the "Data" part. If it has to deal with getting or saving data, it's in the model. If you have a web application, the model is usually where you interact with a database or a filesystem.
Model in MVC is a place where data presented by the UI is located. Therefore, it shouldn't be confused with Domain Model which serves as a skeleton that holds the business logic.
Certainly, for a small application that serves as a service for CRUD operations backed by a database these two models can be the same. In a real world application they should be cleanly separated.
Controller is the one who talks to the application services and the Domain Model. It receives updates back from application services updating the Model which is then rendered by the View.
View renders the state hold by the Model, interprets User's input and it redirects it to the Controller. Controller then decides if the Model is going to be updated immediately or first the information is forwarded to application services.
The Model can represent your "Domain Model" in smaller projects. The Domain Model consists of classes which represent the real-world entities of the problem you're dealing with.
In larger projects, the Domain Model should be separated out of the actual MVC application, and given it's own project/assembly. In these larger projects, reserve the "Model" (i.e. the "Models folder in the MVC project") for UI presentation objects (DTOs - Data Transfer Objects)
The model is respomnsible for managing the data in the application. This might include stuff like database queries and file IO.
the view is obviously the template, with controller being the business logic.
The model is used to represent the data you are working with. The controller controls the data flow and actions that can be taken with the data. The view(s) visualize the data and the actions that can be requested of the controller.
Simple example:
A car is a model, it has properties that represent a car (wheels, engine, etc).
The controller defines the actions that can be taken on the car: view, edit, create, or even actions like buy and sell.
The controller passes the data to a view which both displays the data and sometimes lets the user take action on that data. However, the requested action is actually handled by the controller.
From inside to outside, these are our MVC app layers:
MS SQL / Tables / Views / Stored Procs
Entity Framework 4.1 (ORM) with POCO generation
Repository
Service (retrieve) and Control Functions (Save)
Routing -> Controller -> Razor View
(client) JQuery Ajax with Knockout.js (MVVM)
Everything is fine until I need to create a single ViewModel for step 5 to feed both the Razor view as well as the JSON/Knockout ViewModel:
Header that includes all Drop down list options and choices for the fields below
Items - an array of whatever we send to the client that becomes the ViewModel
Since the Controller won't have access to the Repository directly, does this mean I create a service for each and every view that allows editing content? I'll need to get the POCO from the repository plus all options for each field type as needed.
It just seems redundant to create separate services for each view. For example, a viewModel to edit an address and a separate viewModel to edit a real estate property that also has an address. We could have a dozen forms that edit the same address POCO.
To make this question easier to answer, is allowing the Controller direct access to the repositories a leaky abstraction?
Well, so are your controllers going to have code that translates POCOs from Entity Framework into separate view model objects?
If so, then you should move that code to a separate class, and follow the single-responsibility principle. Whether that class is in the "service layer" or not is up to you. And whether you use AutoMapper or not is up to you. But these kind of data mappers should not be part of the controller logic; controllers should be as dumb as possible.
OK, now let's ignore the data mapping problem, and pretend you could always use your POCOs directly as view models. Then you would still want a service layer, because it would translate between
userService.GetByUserName("bob")
in your dumb controller, and implement that in a specific manner by returning
userRepository.Users.Single(u => u.UserName == "bob")
Putting these together, your UserController ends up taking in IUserService and IUserDataMapper dependencies, and the code is super-dumb, as desired:
public ActionResult ShowUserPage(string userName)
{
var user = userService.GetByUserName(userName);
var viewModel = userDataMapper.MakeViewModel(user);
return View(viewModel);
}
You can now test the controller with stubs for both dependencies, or stub out IUserDataMapper while you mock IUserService, or vice-versa. Your controller has very little logic, and has only one axis of change. The same can be said for the user data-mapper class and the user service class.
I was reading an article this morning that you might find somewhat illuminating on these architectural matters. It is, somewhat condescendingly, titled "Software Development Fundamentals, Part 2: Layered Architecture." You probably won't be able to switch from a database application model to the persistent-ignorant model the article describes and suggests. But it might point you in the right direction.
i personally always inject the repository/repositories into the controller. i'm not sure why you would want to have a service layer between the repository and the controller. if anything you would use specifications.
once you've done that, check out automapper. its a mapper that, once properly configured, can map your domain model to your viewmodel, and back again.
I have an existing application with a datalayer (primary EF4), a businesslayer (custom code) and a windows application - now I want to create a webapplication using ASP.NET MVC but I am not sure exactly what to do especially in my models.
When my data and business logic already exist how should I structure my Models and Controllers compared to a referenceproject like MVC Music Store v2.0 (http://mvcmusicstore.codeplex.com/)? All my entities are stored in my datalayer and all my methods and logic are stored in my businesslayer so I guess I need no Models (unless I need specific web Models) and I guess my controllers will only need to call the methods in my businesslayer as I would to in a normal webform application?
Another question, if I need to display 2 lists with data from 2 different entities on 1 page I guess I need to create af Model with 2 properties (one for each entity)?
The last one for now, if, for some reason, e.g. a Get method from my businesslayer returns an exception how should this be handled in my Controller/View?
It depends on the complexity of your application. I would at the very least introduce ViewModels for each view so you can supply the view with the data that is required. If your application is light weight it might be fine to use your business layer in the controller. However, you might want to introduce a service layer that interacts with your business layer just to keep the controllers thin.
As for exception handling, you might want to look into the HandleError attribute.