When should I create a new controller class in ASP.NET MVC? - asp.net-mvc

I'm learning MVC and am having trouble deciding when I should create a new controller versus just adding an action and view associated with an existing controller. On the one hand, Single Responsibility would seem to say a controller should be limited to a few actions. When I try this, though, the number of classes grows exponentially (model, views and controller for each)- to the point I wonder if I'm going overboard.
For example, the default AccountController has Login, ChangePassword, and Register actions. I would tend to instead create a LoginController, PasswordController, and ProfileController, and related model classes. So where there was 1 class, there would be 3-6.
Is there any good rule of thumb on this?

You should dedicate a controller for each model type you're manipulating. The controller acts as a collection of actions that act upon those models. This is generally the rule of thumb, but sometimes a controller's scope transcends a single model.
The AccountController deals with all things authentication related. This is an example of going beyond a single model's scope to encompass authentication in general. What are the key parts of authentication? Retrieving users, changing passwords, etc.

I think you need to be pragmatic about it. I'm working on a project that consists of a StatsController. The number of actions is continuously growing (RandomStat, MostPopular, MostViewed, MostVoted, etc...) the list goes on and on. These actions are simple to satisfy since the StatsController's dependencies don't change. I'm using an IoC to satisfy what my Controllers need and when I start to see my Controllers needing references to new objects, this is a signal that they need to be broken apart.
If your LoginController, PasswordController, and ProfileController all rely on the same objects, why break them apart?

My current AccountController has 12 methods which to me is completely manageable.
I have another controller which currently has 34 methods but those are all tied to a single view and they each have around 8-10 lines of code max (check required parameters, update the model, and redirect as necessary).
They key is to encapsulate your business logic in an entirely separate module. That will allow your action handlers to remain extremely light weight and can make testing your business logic easier.

Related

Am I misusing or misunderstanding viewmodels in MVC?

I'm using ViewModels in MVC. I'm find them incredibly klutzy and wonder if I'm doing something wrong. (Let's leave Automapper out of this for the sake of discussion.) I use viewmodels to send data to the client as well as receive form submissions. Some properties are sent to the browser for display only, others are sent & retrieved (eg. fields).
I typically have to implement the following to make a viewmodel work:
1) Create a view model class
2) Create a general function to initialize the view model & copy the properties from my entities & other sources
3) Write more code to write some values from the viewmodel back to the entities (or other destination) on submission
4) If there are server side validation errors, I need to write more code (particularly messy) to repopulate the read-only parts of the viewmodel (which were included in the submission), while taking care to not overwrite the user submitted data.
For a simple property (eg. "myViewModel.FirstName") this requires code to be written in no less than 4 places. That's not including the stuff in the Domain and Views. This pattern seems fragile to me - it's easy to break code eg. forget to implement a change in all locations. Definitely not DRY.
Am I missing the point or do all patterns using ViewModel have this kind of klutziness?
I'm not sure what you find klutzy? MVC is about separation of concerns. Keeping your business logic, data layer and GUI code separate. This in itself makes your code easier to manage, easier to test and far less confusing to debug.
And lets look at your four points.
Point 1. Firstly is creating a POCO for your view model really that much of an issue? I'd say not, since you can accomplish this in around 3 lines of code, given your example. And should your model need to change, would it not be more beneficial for it to be in its own view model class rather than in code directly in every action method in every controller where you may have used it?
Points 2 + 3. Here you speak about going from data layer to logic layer to view and back again. This is the whole point of MVC. Just because you have to possibly code three classes (model, service, repository) to handle this transaction does not make this cumbersome, it makes it clean. Just imagine if you dumped all this together on the controller action method. How would you handle re-use? How would you prevent repetition of code in other actions or controllers? Things would start to get very difficult.
Point 4. I don't really see this as a valid argument since you can just pass back the model submitted by the user without any need to update it or edit it. By using data annotations and ModelState for validation it is very simple to create a clean and testable unit of code. So I imagine that its not the fact your using a ViewModel but perhaps more to do with your implementation.

Why do we use ViewModels?

I have recently started working as a web developer. I work with ASP .NET MVC 4 and NHibernate.
At my work-place, we are strictly made to use viewmodels to transfer data to and fro between a controller and a view. And the viewmodels are not supposed to contain any object of a model.
I understand that it is a sort of a tier between the controller and the view.
But I find it repetitive and redundant to write a viewmodel class even if we can directly send the model's object to the view (in most cases).
For example, if i want to display an order i can do this in the controller's action -
return View(Repository.Get<Order>(id));
But instead, I have to write a viewmodel, fill it with the fetched order and then pass it to the view.
So, my question is, what purpose does writing viewmodels serve when we can use the model's object as it is?
For smaller projects, you're right. I hear your argument and sympathise - however there are good reasons for this, drudged and repetitive work, especially in larger and more complicated applications:
It's essential to perform all processing within the Controller's action. However in the example you've given, the Repository.Get method might return a lazily-evaluated IQueryable object, which would mean the DB wouldn't be hit until the View is evaluated. For a variety of reasons this is bad. (A workaround is to call .ToList while still in the controller).
"A view should not contain any non-presentational logic" and "You should not trust the View" (because a View could be user-provided). By providing a Model object (potentially still connected to an active DatabaseContext) a view can make malicious changes to your database.
A View's data-to-display does not always map 1:1 with its Model's data, for example consider a User Details page:
A User's EF Model object represents its entity in the database, so it probably looks like this: User { UserId, UserName, PasswordHash, PasswordSalt, EmailAddress, CreatedDate }, whereas the fields on a "User details" page are going to be User { UserId, UserName, Password, ConfirmYourPassword, EmailAddress }, do you see the difference? Ergo, you cannot use the EF User model as the view model, you have to use a separate class.
The dangers of model manipulation: if you let ASP.NET MVC (or any other framework) do the model binding to the incoming HTTP POST Request then (taking the User details example above), a user could reset anyone's password by faking the UserId property value. ASP.NET will rewrite that value during binding and unless you specifically sanitize it (which will be just as drudgeful as making individual ViewModels anyway) then this vulnerability will remain.
In projects with multiple developers working in a team situation, is is important that everything is consistent. It is not consistent to have some pages using bespoke ViewModels but other pages using EF Models because the team does not share a concious mind, things have to be documented and generally make-sense. For the same reason a single developer can get away without putting excessive XML documentation in his source code, but in a team situation you'll fall apart if you don't.
There is a slight workaround in your case I'll share with you, but please note the preconditions:
Your views can be fully trusted
Your views contain only presentational logic
Your application is largely CRUD
Your views correspond 1:1 with each EF entity model (i.e. no JOINs)
Your views only deal with single Simple models for POST forms, not Complex models (i.e. an object graph)
...then you can do this:
Put all one-way, non-form-related data into your ViewData collection, or the ViewBag in MVC 4 (or even a generic ViewData<T> if you're hardcore). This is useful for storing HTML page titles and sharing data with Master pages.
Use your fully-evaluated and loaded EF models as your View<TModel> models.
But use this approach with caution because it can introduce inconsistency.
Well, i'm starting to think the pragmatic approach to every problem is required and not to just subscribe to the purist architectural standards out there. Your app may be required to run in the wild and be maintained by many developers serving a large set of client etc. and this may direct or drive your architecture.
The ViewModel is essential when you want a separation of concerns between your DomainModel (DataModel) and the rest of your code.
The less dependencies you have between the Model, View and Controller the easier down the line it will be to make changes to the DomainModel without breaking the interface contracts in the View and Controller etc. etc. But once again it's something to be pragmatic. I like the approach as code re-factoring is a big part of system maintenance - refactoring may include a simple spelling mistake on a property of a Model - that change could ripple through the code to the Contract level if the dependencies are not separated; for example.
The ViewModel is used to translate the data between your DomainModel and you Views
A simple example of a datetime stored in Informix has to be translated to a .Net DateTime. The ViewModel is the perfect place to do this translation and does not force you to put translation code in all sorts of unwanted places.
One attribute of a good design [of anything] is the ability to replace or modify a part of the implementation with little or no affects to the rest of the parts of the system. But this takes effort and time to achieve - it's up to you to find that practical balance between a perfect design and a design that is just enough
But yeah, there are many other good reasons to use certain patterns - but the bottom line is this:
Nothing forces you to use ViewModels... ASP.NET MVC won't force you. Take advice from the pragmatist inside you.
If you use same Models as your ViewModels, your application should be very small and simple and should contain only CRUD operations. But if you are building large or enterprise applications with large teams (with two or probably more developers), you should have concepts like Dependency Injection, Services, Repositories, Façades, Units of Work, Data Access Objects etc.
To simplify your mapping needs between Models and ViewModels, you can use AutoMapper
https://github.com/AutoMapper/AutoMapper
or install with nuget
Install-Package AutoMapper
According to me, it is essential to have one more layer(ViewModel) on top of Model layer for complex applications that performs most of the CRUD operations because it has following advantages:
To establish loose coupling between Model and Controller. So that any DataModel related modifications will not be affected to Controller.
If you've implemented your application's ViewModel layer correctly
by providing maximum level of IOC(Inversion of Control) via
DI(dependency Injection using Unity/other frameworks), etc., it will
also help you to MOQ your ViewModels(dependencies) for testing only
the controller's logic.

Is it considered bad practice to write db queries in a controller rather than a model

I've read that best practice dictates fats models, skinny controllers.
Models should contain business logic such as getting a list of customers based on parameters sent from a controller.
Controllers should contain just enough logic to invoke methods within a model to return to a view.
However I see many examples and tutorials where there is logic within the controller such as a query that accesses a db to get a list of products. I was under the impression that the logic should live in a method inside a model. The controller can then invoke this method, rather than containing the actual logic to query the database.
So if I have a ProductController I might have a Index action which returns an Index View, and I would have a ProductModel which would house my logic to display certain products based on a query string(which the ProductController would pass to said model). Right?
So if I have a ProductController I might have a Index action which returns an Index View, and I would have a ProductModel which would house my logic to display certain products based on a query string(which the ProductController would pass to said model). Right?
That is correct. As per the Model-view-controller architecture:
The model manages the behavior and data of the application domain,
responds to requests for information about its state (usually from the
view), and responds to instructions to change state (usually from the
controller). In event-driven systems, the model notifies observers
(usually views) when the information changes so that they can react.
The view renders the model into a form suitable for interaction,
typically a user interface element. Multiple views can exist for a
single model for different purposes. A viewport typically has a one to
one correspondence with a display surface and knows how to render to
it.
The controller receives user input and initiates a response by making
calls on model objects. A controller accepts input from the user and
instructs the model and viewport to perform actions based on that
input.
Keep the data-related queries and operations in the model; stuff as much as you can in there in accordance with DRY (Don't Repeat Yourself). Make the functions reusable as much as possible so they can be ported into various controllers and used throughout the application as necessary.
The view should contain little - if any - logic outside of view-specific work.
Your controller functions should invoke the model functions required to retrieve and manipulate data, and should be as "thin" as possible (as you pointed out). The smaller and less involved the controller, the easier it will be to add asynchronous features that "don't reboot the application" on the front-end, making for a better user experience. (If you are concerned about this, anyway!)
The Add Controller dialog box in VS 2010 has the option of adding a scaffold with CRUD functions into the controller. This should tell you quite a bit above how the ASP.NET MVC dev. team views this debate.

God Controllers - How to prevent them?

In a few MVC projects I've been working on, it has become apparent that there are a few problematic controllers that have organically grown into God classes - demi-gods each in their own domain, if you will.
This question might be more of a matter 'what goes where,' but I think it's an important question with regards to SRP (Single Responsibility Principle), DRY (Don't Repeat Yourself), and keeping things concise, "agile" -- and I am not experienced enough (with this pattern and in general design) to be knowledgeable about this.
In one project, we have a NutritionController. Over time it's grown to include these actions (many with their respective, GET, POST, and DELETE methods):
Index (home controller)
ViewFoodItem
AddFoodItem
EditFoodItem
DeleteFoodItem
ViewNutritionSummary
SearchFoodItem
AddToFavorites
RemoveFromFavorites
ViewFavorites
Then we have an ExerciseController, which will include many similar actions, such as the searches, and favorites actions. Should these be refactored into their own controller so that it's something like so?
SearchController {
SearchExercise
SearchNutrition
//... etc
}
FavoritesController {
ViewNutritionFavorites
AddToNutritionFavorites
AddToExerciseFavorites
EditNutritionFavorites
EditExerciseFavorites
//... etc
}
It just seems to me that if you break them out into separate controllers, you're going to grow an unbelievably large dependency at some level to deal with the information that you will need. OR you are going to have a completely generic handling application that will be very difficult to handle since you will have to jump through so many hoops to get your desired effect (either at the M, V, or C level).
I am thinking about this the wrong way? For example, should I have a generic Favorites object and then let the controller decide what view to throw it to?
*Sorry for spelling out the acronyms -- I'm doing so in case anyone else comes across this question and is clueless as to what those things are
EDIT:
All the logic I perform is pretty much handled in the service layers. For example, the controller will send the 'new' FoodItem to the service. If it already exists, or there's an error with it, the service will bubble it back up to the controller.
I would break your first list up based on responsibility:
HomeController
Index
FoodItemController
ViewFoodItem
AddFoodItem
EditFoodItem
DeleteFoodItem
SearchFoodItem
NutritionController
ViewNutritionSummary
FavoritesController
AddToFavorites
RemoveFromFavorites
ViewFavorites
SearchFavorites
Django's approach to MVC is to separate responsibilities into "applications", each with their own models, controllers, and even templates if necessary. You'd have a Food app, a Nutrition app, a Search app, and a Favorites app, most likely.
Edit: The OP mentioned that searching is more specific to each controller, so I've made those actions. However, searching may also be just a general global thing, so in those cases, a SearchController would be fine.
Do as Soviut says. You want to keep the controllers simple. It sounds like your ending up with too much coordination logic in your controllers. Remember they are responsible for hooking up a view and a model. This coordination logic should probably be split out into services.
I get this feeling because you mention the possibility of your controller growing huge dependencies. Well If FavoritesController needs to know about nutrition AND exercise favorites (to display in the same view) don't make your controller dependent on 2 repository like classes. Instead, encapsulate that coordination behavior. Maybe create a FavoritesService that knows how to return both nutrition and exercise favorites. That service might delegate to NutritionFavoritesService and ExerciseFavoritesService. This way you're controller only ends up with 1 dependency, you're keeping things DRY, enforcing the SRP, and concentrating your business logic in some place other than the controller.
I'm not too familiar with that framework, but I can offer a bit of general advice. A controller should probably only know how to complete a single action, or to invoke other, single action controllers to complete a sequence of related actions. Any information that must be passed around from action to action should probably be somehow passed through the model layer, since that information is most likely relevant to the underlying model.
I have also experienced these sorts of maintenance headaches and find sticking to a "Rails" like method to be very helpful in keeping my controllers focused and unbloated.
If I find myself adding actions with unusual names Eg. To use a blogging example, AddPostToBlog, that would be a flag to create a new Post controller with a Create action.
In other words, if the action is not either one of the Index, New, Create, Show, Edit, Update and Destroy actions, then I add a new controller specific to the action I require.
For your example.
SearchController {
SearchExercise
SearchNutrition
//... etc
}
I would refactor this to...
SearchExerciseController {
Index
}
SearchNutritionController {
Index
}
This may mean having more controllers, but in my opinion thats easier to manage than ever expanding "god" controllers. It also means that the controllers are more self documenting.
Eg. Does the SearchExercise action, return the View to search the exercise or does it actually perform the search? You could probably ascertain this by looking at parameters and body, but its not as easy as for example a New and Create, or Edit and Update action pair.
SearchController {
SearchExercise
}

Rails Model, View, Controller, and Helper: what goes where?

In Ruby on Rails Development (or MVC in general), what quick rule should I follow as to where to put logic.
Please answer in the affirmative - With Do put this here, rather than Don't put that there.
MVC
Controller: Put code here that has to do with working out what a user wants, and deciding what to give them, working out whether they are logged in, whether they should see certain data, etc. In the end, the controller looks at requests and works out what data (Models) to show and what Views to render. If you are in doubt about whether code should go in the controller, then it probably shouldn't. Keep your controllers skinny.
View: The view should only contain the minimum code to display your data (Model), it shouldn't do lots of processing or calculating, it should be displaying data calculated (or summarized) by the Model, or generated from the Controller. If your View really needs to do processing that can't be done by the Model or Controller, put the code in a Helper. Lots of Ruby code in a View makes the pages markup hard to read.
Model: Your model should be where all your code that relates to your data (the entities that make up your site e.g. Users, Post, Accounts, Friends etc.) lives. If code needs to save, update or summarise data related to your entities, put it here. It will be re-usable across your Views and Controllers.
To add to pauliephonic's answer:
Helper: functions to make creating the view easier. For example, if you're always iterating over a list of widgets to display their price, put it into a helper (along with a partial for the actual display). Or if you have a piece of RJS that you don't want cluttering up the view, put it into a helper.
The MVC pattern is really only concerned with UI and nothing else. You shouldn't put any complex business logic in the controller as it controls the view but not the logic. The Controller should concern itself with selecting the proper view and delegate more complex stuff to the domain model (Model) or the business layer.
Domain Driven Design has a concept of Services which is a place you stick logic which needs to orchestrate a number of various types of objects which generally means logic which doesn't naturally belong on a Model class.
I generally think of the Service layer as the API of my applications. My Services layers usually map pretty closely to the requirements of the application I'm creating thus the Service layer acts as a simplification of the more complex interactions found in the lower levels of my app, i.e. you could accomplish the same goal bypassing the Service layers but you'd have to pull a lot more levers to make it work.
Note that I'm not talking about Rails here I'm talking about a general architectural style which addresses your particular problem.
Perfect explanations here already, one very simple sentence as conclusion and easy to remember:
We need SMART Models, THIN Controllers, and DUMB Views.
http://c2.com/cgi/wiki?ModelViewController
The Rails way is to have skinny controllers and fat models.
Do put stuff related to authorization/access control in the controller.
Models are all about your data. Validation, Relationships, CRUD, Business Logic
Views are about showing your data. Display and getting input only.
Controllers are about controlling what data goes from your model to your view (and which view) and from your view to your model. Controllers can also exist without models.
I like to think of the controller as a security guard/receptionist who directs you the customer(request) to the appropriate counter where you ask a teller (view) a question. The teller (view) then goes and gets the answer from a manager (model), who you never see. You the request then go back to the security guard/receptionist (controller) and wait until you are directed to go another teller (view) who tells you the answer the manager (model) told them in response to the other teller's (view) question.
Likewise if you want to tell the teller (view) something then largely the same thing happens except the second teller will tell you whether the manager accepted your information. It is also possible that the security guard/receptionist (controller) may have told you to take a hike since you were not authorized to tell the manager that information.
So to extend the metaphor, in my stereotyped and unrealistic world, tellers (views) are pretty but empty-headed and often believe anything you tell them, security guard/receptionists are minimally polite but are not very knowledgeable but they know where people should and shouldn't go and managers are really ugly and mean but know everything and can tell what is true and what isn't.
One thing that helps separate properly is avoiding the "pass local variables from controller to view" anti-pattern. Instead of this:
# app/controllers/foos_controller.rb:
class FoosController < ApplicationController
def show
#foo = Foo.find(...)
end
end
#app/views/foos/show.html.erb:
...
<%= #foo.bar %>
...
Try moving it to a getter that is available as a helper method:
# app/controllers/foos_controller.rb:
class FoosController < ApplicationController
helper_method :foo
def show
end
protected
def foo
#foo ||= Foo.find(...)
end
end
#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...
This makes it easier to modify what gets put in "#foo" and how it is used. It increases separation between controller and view without making them any more complicated.
Well, it sort of depends upon what the logic has to deal with...
Often, it makes sense to push more things into your models, leaving controllers small. This ensures that this logic can easily be used from anywhere you need to access the data that your model represents. Views should contain almost no logic. So really, in general, you should strive to make it so that you Don't Repeat Yourself.
Also, a quick bit of google reveals a few more concrete examples of what goes where.
Model: validation requirements, data relationships, create methods, update methods, destroy methods, find methods (note that you should have not only the generic versions of these methods, but if there is something you are doing a lot, like finding people with red hair by last name, then you should extract that logic so that all you have to do is call the find_redH_by_name("smith") or something like that)
View: This should be all about formatting of data, not the processing of data.
Controller: This is where data processing goes. From the internet: "The controller’s purpose is to respond to the action requested by the user, take any parameters the user has set, process the data, interact with the model, and then pass the requested data, in final form, off to the view."
Hope that helps.
In simple terms, generally,
Models will have all the codes related to table(s), their simple or complex relationships (think them as sql queries involving multiple tables), manipulation of the data/variables to arrive at a result using the business logic.
Controllers will have code/pointers towards the relevant models for the job requested.
Views will accept the user input/interaction and display the resultant response.
Any major deviation from these will put unwanted strain on that part and the overall application performance may get impacted.
Testing, Testing ...
Put as much logic as possible in the model and then you will be able to test it properly. Unit tests test the data and the way it is formed by testing the model, and functional tests test the way it is routed or controlled by testing the controllers, so it follows that you can't test the integrity of the data unless it is in the model.
j

Resources