This is in a class called Authentication Service which is called from my LoginController. The authentication service is wired up to the LoginController using Dependency Injection via Windsor by way of MvcContrib. Consider that foreshadowing.

The key to the error is the _httpContext variable. It is set in the constructor of the AuthenticationService as follows:

Some of you will recognize this as poor man’s dependency injection, used primarily because I didn’t feel like wrapping the HttpContextWrapper2 class (which is itself a wrapper) in an interface. Some of you will also note that even though I’m injecting the HttpContext into this class, it is still largely untestable because of the FormsAuthentication stuff. Frankly, I’m good with that which is why I didn’t bother with the interface.

During my debugging, one of the things I did was replace _httpContext with HttpContext.Current and lo! That works fine. So clearly, my poor man’s dependency injection had issues. My mentor application, CodeCampServer, went the extra step and created an IHttpContextProvider interface around HttpContextWrapper2 and used Windsor to wire it in:

One of the nice things that came out of this was that, thanks to my auto-registration code, I didn’t need to do anything special to wire in the new IHttpContextProvider class. Just created it and it just worked. Who knew?

As for the cause of the error, I can only speculate. My guess is that it was using the wrong HttpContext. During my debugging, the constructor for AuthenticationService would get called during the first call to the Login page. That is, when the Login page was first rendered. So the class was storing a reference to *that* page’s HTTP context. When the user logged in, it would use that context and try to add the authentication cookie to it. Since that context had already been used and the headers written out, the error occurred. So it wasn’t actually getting the *current* HTTP context. It was using the previous request’s context.

Further proof of this theory: when I would see that error, my workaround was to go back to Visual Studio and do a full re-compile of the application. This clears out the cached version of the class, and more importantly, it’s reference to the previous request’s HTTP context. When I’d refresh the page, it would have to create a new instance of AuthenticationService and use the current request’s HTTP context, which hasn’t yet completed.

In the new version, every call to GetCurrentHttpContext will create a new HttpContextWrapper2 object based on the current request’s HTTP context. Ergo, we will always have the current context.

@Jason: I had not seen that. Looks interesting though perhaps a little bit of overkill for my requirements, especially since I’ve already got the authentication working. Will take a look when my requirements get more complex though.

http://huntjason.spaces.live.com JH

Kyle,
Not certain if you’ve already come across it already, but the MVC Membership Starter Kit has give us a good headstart on authentication stuff on our project.

As I mentioned, managing the cookie yourself is a possibility. But that’s what FormsAuthentication is there for, to do it for you. To check if someone is authenticated, you need only call: HttpContext.Current.User.Identity.IsAuthenticated.

FormsAuthentication is an entirely separate concept from WebForms and MVC. It doesn’t use the ASP.NET Lifecycle, which is the typical target for people moving away from WebForms. You could just as easily manage the cookies yourself in WebForms.

Joe

I just don’t know why there’s a need for FormsAuthentication. You can set the cookie yourself and validate it’s existence before each action call (via some inherited controller).

Kyle Baley

@Andy: My original implementation didn’t use Windsor at all. It used poor man’s dependency injection. But yes, it was stateful. Really, I could have fixed this by not creating an HttpContextWrapper2 object in the constructor but in the SignIn method itself. When I switched to using Windsor, it worked because my auto-registration code adds objects as transient.

Andy Hitchman

Your original implementation of the AuthenticationService was stateful.
I’d guess that you need to mark the component as transient so Windsor constructs a new instance per resolution. By default (IIRC), it caches component instances which effectively act as singletons.

Kyle Baley

Oh, and the concept of forms *does* exist in MVC. It’s WebForms, the abstraction over HTTP forms, that MVC tosses out.

Kyle Baley

MVC obviates the need for a lot of things but authentication is not one of them. I still have the need to store a user’s identity across a session. And FormsAuthentication is still useful in this regard.

Note that FormsAuthentication doesn’t make use of ViewState, the chief target of MVC-proponents. It’s an abstraction over cookies. Without it, I’d have to manage the cookies used for authentication myself.

I sound a lot more confident than I really am in this regard. In reality, I stole the code from CodeCampServer

Joe

Ok…but what’s that got to do with FormsAuthentication? I’m just curious as in why you’re using it if the whole concept of forms doesn’t even exist in MVC.

Kyle Baley

@Joe: Although the app is meant to be used internally, the company is small enough that they don’t have the infrastructure in place to host it internally. Hence, it will be hosted externally.