Reputation: 906
I am pretty new to MVC and am having difficulties getting my application to run on my staging webserver. On my local machine and dev server it is running fine.
The issue is that in my Action the User is null (on staging, not on dev and local). I googled reasons why the User would be null, but everything seems covered. Strange thing is that it works perfectly on 2 servers.
Here is my code...
In Global.asax Using PostAcquireRequestState I override the principal using a custom principal holding an object stored in Session. Hence the SessionHelper which will get the object and add it to the principal. The principal is then set to the httpcontext and thread.
public class MvcApplication : HttpApplication
{
public MvcApplication()
{
PostAcquireRequestState += new EventHandler(MvcApplication_PostAcquireRequestState);
}
void MvcApplication_PostAcquireRequestState(object sender, EventArgs e)
{
if (Context.User is ICSPrincipal)
return;
var principal = new ICSPrincipal(new GenericIdentity(User.Identity.Name), SessionHelper.UserClaims);
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = principal;
}
...
}
In my controller I will retrieve the value stored in the principal. But the problem is that User is null on my staging server. It works however on my local machine and my development server. Development server and staging server are running the same version of IIS and both have MVC3 installed.
public class HomeController : Controller
{
public ActionResult Index()
{
//PROBLEM!!! User is NULL on staging server.
var userClaims = ((ICSPrincipal)User).UserClaims;
...
}
}
Does anyone have any experience with this problem and got it solved? I was under the impression I could safely call User from within my Action.
EDIT: Situation sketch on why I require SessionStorage in combination with a custom principal.
I use formsauthentication so the authentication is covered. However I used to store an object which held extra userdata (firstname, lastname; 6 properties in total) into the userdata from the authentication cookie. However investigating my requests I saw that each request (even for images; and I know I can optimize this using a cookieless domain, but that's a next step) was over 2.5KB. Therefor I switched back to just storing username in the cookie and on each request I want the data to be completed from session storage. That's why I thought a custom principal would be great. It starts with a generic principal and once we get to the Action there is a custom principal with all the data I require coming from wherever I want (in this case username from cookie added with data from session).
I hear you say: but hey, using Session is not safe, it expires after a while. And I am well aware of this, that's why SessionHelper has ofcourse some intelligence. If the Session object is null, it will get all data required based on the authenticated user's username. It than stores this data in Session so subsequent requests don't query my database.
I also use API communication (http or named pipes) and that's why I need this data in the custom principal. I can't access Session from that layer, but I can access the principal. Therefor if the principal is updated before getting to that communication everything works fine.
GETTING TO THE ACTUAL PROBLEM:
This setup described above actually works fine on multiple machines, but not on my staging server which is the same setup as my development server. Staging complaints that User is null in my action. And I don't know how that's even possible.
Upvotes: 0
Views: 2799
Reputation: 906
http://support.microsoft.com/kb/980368/en
After this patch is applied, ASP.NET 4 applications can handle requests for extensionless URLs. Therefore, managed HttpModules that run prior to handler execution will run. In some cases, the HttpModules can return errors for extensionless URLs. For example, an HttpModule that was written to expect only .aspx requests may now return errors when it tries to access the HttpContext.Session property.
This has fixed the issue! Thanks all for making me experiment with multiple settings. This way I came up with this solution.
Upvotes: 0
Reputation: 93424
PostAcquireRequestState is an odd place to be doing this. You should be doing it in AuthenticateRequest. you should also set Context.User not HttpContext.Current.User.
Upvotes: 2