I recently asked a question about using the Page.User or HttpContext.Current.User in the View. It was recommended I pass the user info through the Controller instead? I've seen this in other posted answer as well.
Why is it recommended to pass the user info through the controller and not use Page.User or HttpContext.User?
This would only be pragmatic if your automating your view testing with Selenium or using some other tool to check your HTML output.
If that is the case using HTTPContext inside your controllers is probably a really bad idea because that will only increase the coupling between your controller actions and HTTPContext.
To gain maximum testability you probably want to setup a controller factory that can inject the User bits into your controller when MVC calls it. That way your action methods remain decoupled from HTTPContext and you gain testability.
If your not using a automated view testing tool it doesn't really matter were you call your HttpContext.User information unless your doing a lot of logic in your view. For example if( HttpContext.User.IsAuthenticated ) or something. If that is the case you can just stick it inside a control and use RenderPartial or bake the logic bits into your viewmodels.
A recommended best practice for MVC is to keep your Views as dumb as possible. Yet, I'd advice against getting all dogmatic about MVC and patterns and what not. Because MVC does not have baked in SubController functionality there are many areas were breaking the MVC pattern is not only encouraged but impossible to not break otherwise. ( see MVC 2 RenderAction, RenderPartial, MasterPages with controls )
Controller should provide all necessary data for view. This makes views more testable. If you use only view model inside view, you can easily write test:
Create view model.
Create view object.
Pass model to view.
Render view.
Check if result is correct.
If you used HttpContext.Current inside of view, you would have to set it up first in your tests, which may not be easy and would add additional dependencies.
It loosens the coupling between your controller and the other classes in the application. By using more of a Dependency Injection pattern, you can increase the testability of the controller. This is because in your tests you would not need to simulate concepts like HttpContext but could simply pass in the user object.
Related
With ASP.NET MVC3 what would be the best way to register the requests ControllerContext into castle windsor container? Ultimately I'd like to be able to say
container.Resolve<ControllerContext>();
and have the requests controller context returned.
More detail
The vast majority of my actions are just going to do some validation, authentication, etc.. before sending a message to nservicebus to actually do the work. To avoid having to copy/paste these 20/30 lines of code all over the place I have put them into a handler class which my controllers take a dependency on in the constructor, the actions then call this class which leaves my actions containing just one line of code.
One of the child classes that makes up the handler needs to know about the route that was taken, I could just pass the controller to the handler and then onto this class but it seems a bit messy. It would be nice if there was a way to get Windsor registered to provide it for me.
I don't think you can register the ControllerContext without some very ugly hacks, and IMHO it's not a good idea anyway. The ControllerContext belongs to the controller, it's not meant to be shared around.
However, if you only need the routing information, you can register it like this (UNTESTED!):
container.Register(Component.For<HttpContextBase>()
.UsingFactoryMethod(() => new HttpContextBaseWrapper(HttpContext.Current))
.LifeStyle.PerWebRequest,
Component.For<RouteData>()
.UsingFactoryMethod(k => RouteTable.Routes.GetRouteData(k.Resolve<HttpContextBase>()))
.LifeStyle.PerWebRequest);
Also see ASP.NET MVC & Windsor.Castle: working with HttpContext-dependent services for more details.
I don't know concretely what you're trying to achieve but I'd look into doing it with filters or custom ActionResults instead.
Not really an answer to the original question but I can't stand dubious architectural moves :) It seems for me like ControllerContext isn't a best (well, not even a good one) place to try to extend from. The ModelBinders and ActionAttributes are the places to help with repeating code. They can take model mapping, binding and validation on their own thus freeing controllers from that responsibility.
Well, generally, what you'd really want to do is to use Dependency Injection for Controllers themselves injecting configured instances of somewhat IAuthenticationService and IValidationService (concrete implementations of them would contain all those 20/30 reusable lines of code). Then in Controllers you just call them in one line of code (or even use the MVC3 Global Filters feature to make that completely transparent).
I'm familiar with the various bits of functionality of the MVC plugin to create things. For example you can create a controller, write an Action method on it, then use the "create view" function in the context menu to create a view for it.
The question is, which is it recommended to do first?
I'm thinking I might start myself a methodology like this:
Plan out what the UI etc will look like and how it will work.
Write unit tests for the controller actions I think I might need.
Create Controller (maybe with default CRUD actions if it's to be that kind of controller).
Create ViewModel class for each controller action.
Create a strongly-typed view for each ViewModel.
Start building the view, working back through the ViewModel to the Controller as the View is built up.
What do you think of this approach, and what do you do?
Sounds like you're on the right track. Controllers are the most easily tested component of the three. Going controller-first will make it easier to follow Test-Driven Development practices.
I've not been perfectly happy with the default view templates, but every MVC guru will point you to T4 templates, which let you roll your own. They, like the out-of-the-box view templates, will be more effective with existing view models and controllers.
I'd be tempted to define the ViewModel first, the VM(s) can consist of all or a subset of the entities required for the various Views. How you segregate your VMs would depend on your app and how you are breaking up logical units within that.
Once I had the VM(s) in a basic form I would move to Model necessary for my chosen data store (unless I had an existing data store in which case I'd have started with the Model). Then onto the controllers. You can then apply TDD with a mocked data source to verify that the VM objects returned by the controller actions match expectations. Lastly, I'd generate basic strongly typed Views (based on the ViewModel objects) for each controller action that actually resulted in UI.
Then it's play time with Jquery and CSS to make it look presentable.
i have several controllers which will all be using common functionality. So i have separated that functionality into a separate controller.
the shared controller needs a parameter specific to which controller it is being used from, and needs to return views based on id ints passed to it.
So, one idea is to create an instance of SharedController(int callingControllerId) in the constructor of each of the controllers that will be using it. Then, within the action methods of each controller, call the action methods of the shared controller, passing appropriate ids, and returning views from SharedController to the calling controller, which would return the view to be rendered.
Does this sound right? Should controllers be creating other controllers in MVC?
Thanks!
Absolutely not although having your controller inherit from a shared, base controller is pretty common.
public KittyController : MySharedBaseController
{
}
Like Greg Roberts points out that although having a ControllerBase is common it is not always the best place to store shared functionality. MVC has a lot of extensibility points and picking a narrow place to wedge in your code is a lot better than smushing tons of things into a base controller.
I would agree that a base controller is pretty common, but I'm not sure it's the right solution for what you are describing.
Without knowing what is exactly shared it's a bit hard to figure out, but the whole bit of your base controller knowing specifics about the controllers that are inheriting from it smells a bit.
Here are a couple things to consider.
Composition is almost always better than inheritance. Great article on this
Base controller should have common methods/properties, for example mine have some properties of getting the current user and a generic method for calling external services, but not specific things from inheriting controllers. Rule of thumb, if it's not needed by more than 1 controller, than probably not good in base implementation.
It's possible that some of the new MVC 2 features might solve what you are doing. Look at render action.
As with anything in software, there are tons of ways to solve the problem, so ultimately do it the way that makes the most sense to you and your team.
Controllers are constructed by the ASP.NET MVC runtime and you should never be constructing them in your own code. It sounds like you don't really need a separate controller, you just need another class that you aggregate in the controller, and use as a service. This is perfectly acceptable. In fact, I would go so far as to say that in general controller should be delegating their work to other "service" classes and shouldn't have much responsibility (especially domain logic) in and of themselves.
I don't know the details of why this service class needs to know what controller it is being called from, but perhaps you can just declare an enum that defines the different use cases, and pass that in in its constructor. Actually having the service class know about different controllers would be a code smell for me.
In our standard web forms ASP.NET solutions we typically have a range of user controls within the master page and determine whether they display or not within their code behind. What is the best approach within ASP.NET MVC to achieve the same goal?
You could obviously put if statements within the master page or the partial view but that strikes me as messy and breaks the principle of keeping business logic out of the view. It also requires either putting the necessary information into all view models, or inheriting from a base controller which seems like a lot of messing about for something so simple.
I was thinking about using RenderAction and returning a totally blank view to prevent any output - is that a good pattern?
breaks the principle of keeping business logic out of the view
It is not business logic. It is presentation logic when you determine whether to display something or not. It is okay to have it there.
You can make decision whether to display something or not and set up a few flags in the model (you can make BaseModel or MasterModel for example). Then your master views, partial views themselves or HTML helpers will perform conditional rendering based on these flags.
As to the clean separation of concerns, yes, the WebForms could seemingly do it but it was rather a huge abstraction of the underlying mechanisms. Often it results in having business logic in the code-behind, meaning, in the presentation layer where business logic belongs no more than it belongs to the views.
You could avoid the messy "If" statements in view by creating a Html extension method as mentioned in my recent post http://www.rajeeshcv.com/2010/01/asp-net-mvc-conditional-rendering-partial-views/
Thanks,
Rajeesh
I'm trying to learn the new ASP .NET MVC framework and would like to know the best practice for using UserControls.
I understand that you can render UserControl's as a partial and pass data to them from a controller. Ideally I would think that it makes sense not to have a code behind file as this creates a temptation to break the MVC rules.
I'll give an example where I don't understand how UserControls fit into the pattern.
I have a UserControl that shows the
latest tags (much like on
StackOverflow). Unlike StackOverflow I
want to display this UserControl on
all of my pages. If I have a
controller say QuestionController
which is meant to handle actions from
some question views e.g. view and
detail, does this mean I have to fetch
the data in the QuestionController and
then pass it to the UserControl?
If I create another controller say
SearchController then I would have to
replicate the same functionality to
get the latest tags to pass to a
partial again. Doesn't this mean that
the 2 different controllers are doing
extra things that they weren't
originally intended to do?
If your UserControl appears on every page, then one way to address this would be to use a base controller from which all of your controllers derive and generate the ViewData for the UserControl by overriding the OnActionExecuting method and putting the logic there. If your UserControl is less pervasive, but still frequently used throughout the site, you could extend ActionFilterAttribute and have your filter generate the needed data. This attribute could be used to decorate the controllers or actions that generate views that use the UserControl.
I'm assuming in all of this that the data for the UserControl is independent of the action being invoked. If there is a dependency, it's probably best to push the logic into a class (or classes, perhaps using Strategy) and make the generation of the data explicit in each action or controller (via overriding OnActionExecuting).
Alternatively, with ASP.NET MVC 2 you can now use RenderAction to call a completely new controller action which can fetch the data. This makes your code much more modular and it is more clear where the data is coming from.
You can also consider putting your model classes in an hierarchy. The upper class (or one of the upper classes) will contain data necessary for your pervasive user controls. Then you can load these commonly used data in a base controller class.