Search code examples
c#asp.net-mvccontrolleruser-controlshttpcontext

Why is User (as in User.Identity.Name) null in my abstract base controller?


I was asking a related question but messed the title up and no-one would understand it. Since I am able now to ask the question more precisely, I decided to reformulate it in a new question and close the old one. Sorry for that.

So what I want to do is passing data (my custom user's nickname as stored in the db) to the LoginUserControl. This login gets rendered from the master page via Html.RenderPartial(), so what I really need to do is making sure that, say ViewData["UserNickname"] is present on every call. But I don't want to populate ViewData["UserNickname"] in each and every action of every controller, so I decided to use this approach and create an abstract base controller which will do the work for me, like so:

public abstract class ApplicationController : Controller
    {
        private IUserRepository _repUser;

        public ApplicationController()
        {
            _repUser = RepositoryFactory.getUserRepository();
            var loggedInUser = _repUser.FindById(User.Identity.Name); //Problem!
            ViewData["LoggedInUser"] = loggedInUser;
        }
    }

This way, whatever my deriving Controller does, the user information will already be present.

So far, so good. Now for the problem:

I can't call User.Identity.Name because User is already null. This is not the case in all of my deriving controllers, so this is specific for the abstract base controller.

I am setting the User.Identity.Name via FormsAuthentication at another place in the code, but I think this can't be the problem - afaik User.Identity.Name can be null, but not User itself.

It looks to me like the HttpContext is not available (since also null ;-) and that I am missing a simple yet important point here. Can anyone give me some hints? I would really appreciate it.


Solution

  • My guess would be that the Controller's base constructor is not filling in the User, but that it is only known later when the ControllerContext is set for the Controller. You should check this in the documentation about the lifecycle of an MVC application, (the one here will probably do, although it might be a bit out of date since it's for the preview version), or just check the source code of MVC.

    from the code that I have of MVC (also a preview version, but that should be fine): (In Controller)

     public IPrincipal User {
                get {
                    return HttpContext == null ? null : HttpContext.User;
                }
            }
    

    ...

    public HttpContextBase HttpContext {
            get {
                return ControllerContext == null ? null : ControllerContext.HttpContext;
            }
        }
    

    I don't see en an implementation of a default constructor in the code. That would prove that the ControllerContext is null at the time of construction.

    So you should execute your code somewhere else.