I am working on an MVC ASP .NET application. I am relatively new to both.
In a controller I am trying to get the current log on user, for which there seem to be two ways of doing this:
System.Web.HttpContext.Current.User.Identity.Name
Or
HttpContext.User.Identity.Name
What is the difference between these? As far as a I can tell within the MVC framework the controller has the current HttpContext stored as a property so these methods are identical. Is that correct?
Yes, they will usually be identical. However, if you're working with additional threads, they will not be; System.Web.HttpContext.Current is threadstatic.
The context provided by the controller (not the static HttpContext.Current) is mockable. If you're interested in unit-testing your code, it's generally far easier to create a mock ControllerContext and set it on the Controller than it is to go through HttpContext.Current. Otherwise ControllerContext.HttpContext points to the same data as HttpContext.Current.
Related
Someone in a post here, commented that you should not use HttpContext.Current when using MVC, rather, you should be using ControllerBase.ControllerContext. In some respects, this makes sense, but in other respects it doesn't.
For example, ControllerContext is an instance variable, so everywhere I want to reference, say, my Session variables, I need to have a reference to the Controller? Why are we "not supposed" to be using HttpContext.Current in MVC, when you still can? Is there an "appropriate" MVC "way" to get at my Session object without having to have a reference to the Controller?
I know test-wise, it is better for reasons stated in many other places, but I am working on a project that manages Session variables and references HttpContext.Current and I want to know if there is a better way to get my hands on the Session object without passing a reference to the controller.
This is mainly since unit testing would be very difficult if you use HttpContext.Current since mocking this value is not possible using normal mock frameworks.
HttpContext.Current also makes for more brittle code since it can be abused and misused. For example, you can use it in business layer since it is convenient but it will break if you choose to use an alternative presentation layer other than ASP.NET.
Generally static methods are nowadays frowned upon since they cannot be dependency-injected.
Your one post was due to Mock testing, where depending on the Mock there may not be a HttpContext, only a controller context. Otherwise, I do use HttpContext.Current, just not in my unit tests.
I asked this question over on the asp.net forums, and nobody seems to know what i'm talking about. I'm not sure why that is, but I figured I'll ask here to see if there is anyone with some insight.
Back when MVC2 was released, it included a sample AccountController that wrapped the built-in Membership and FormsAuthentication classes with testable interfaces and services. I read a lot about this, and it was considered a good thing because the Membership and FormsAuthentication classes were not easily testable.
Recently, I generated a new sample project with my up to date (SP1, MVC3, Tools Update, etc..) environment and I find that the AccountController is now much simpler. Gone are the Interfaces and MembershipService and FormsAuthenticationServices. The sample now calls the Membership and FormsAuthentication classes directly.
I'm wondering if anyone knows when this happened and why? Are the testable interfaces no longer considered correct? Was there a technical reason to change this?
The best I can figure is that this happened as a part of the change to remove a possible vulnerability when passing return url's on the open url.
Any insight?
The new model resembles EF's code first approach where the AccountModel is a POCO class. Inside the new API there are no longer abstractions but direct calls to static methods such as FormsAuthentication.SetAuthCookie making this code difficult to unit test. Not something I would recommend basing your real world application code upon.
And, yes, they have fixed a vulnerability inside the LogOn method which was not verifying if the return url is a relative url before redirecting.
Personally I would recommend you using abstractions in order to weaken the coupling between your controller logic and its dependencies. This will make the code easier to unit test.
For me passing all those domain models to views without using view models are total anti-patterns and I have never bothered with them. I simply create an empty project and do the things my way. I mean in the default project they even use ViewBag for Christ sake!
The Account Controller was changed with the MVC3 tools update (When they also included the use of jQuery via Nuget)
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 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.
Where can I find a good tutorial on TDD with ASP.NET MVC 1.0? I'd prefer a video tutorial but a text tutorial would be fine as well. I have a new project starting soon and I want to start off on the right foot.
The Storefront Videos from ASP.NET are a must watch series.
Any tutorial on TDD will be helpful for MVC. I've been doing TDD for sometime and found that it was a natural transition in MVC. There are a few peculiarities that I have found that need to be addressed.
You often need to mock up the HttpContext, which means that you need to assign a ControllerContext to the controller after it's created as that's the only way to inject the mock. The context will be used to provide the Session, Request, and Response objects in the controller (also mock them). New HttpContextBase, HttpSessionStateBase, ... classes make this much easier to do.
Because of (1), invest some time in putting together some helper classes in a separate class library that can be used by all of your test projects. These helper classes should contain methods that provide configurable (or multiple methods to provide specific configurations) of the mocked contexts. This will help keep your tests compact.
Use and assign a ValueProvider for testing methods that accept parameters if you aren't using ModelBinding (with corresponding parameters in the signature) for a controller action. This will allow you to use TryUpdateModel/UpdateModel without adding code to your controller to get data from the Request into those methods.
Use a mocking framework -- if that isn't obvious from above. It will be so much easier to write your tests if you mock out the dependencies. Writing your own mocks, IMO, is not worth it, though I know others don't share that opinion. I guess this isn't unique to MVC, but I thought I'd mention it.
Set up a separate set of tests that use reflection to test that appropriate attributes with appropriate properties are getting set on your methods. MVC makes heavy use of attributes for security and other cross-cutting aspects. These need to be tested as well.
Check out here. MVC store front is highly recommended.
I thought that Rob Conery's 'ASP.NET MVC Storefront Starter Kit' http://www.asp.net/learn/mvc-videos/#MVCStorefrontStarterKit were great for demonstrating TDD with ASP.NET MVC.