Best practice to set/get information about whether user is logged in or not
I know similar questions have been posed before, but I could not find a duplicate that handles ASP.NET MVC (and the controller aspect) specifically.
My question is as follows:
In a MVC model, my understanding is that the controller should handle the use of HttpContext to determine who is logged on, if any. This is so the controller can present this information to the view, so that the view itself does not have to perform these look-ups.
Is there any defacto standard on how to do it?
My current setup is as follows [simplified]
I have a BaseController
, which all my other controllers inherit.
In BaseCont开发者_JAVA技巧roller
, I perform the following override:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
ViewData["IsUserLoggedIn"] = IsUserLoggedIn; // bool property checking HttpContext.User.Identity.IsAuthenticated;
ViewData["CurrentUser"] = CurrentUser; // Property returning logged in user, or null.
}
Then, naturally, in my Views I can check the ViewData values.
How do you do it? I'd like to know if something is wrong with my setup, and if so, what's wrong? I'm not 100% comfortable with my solution, - mainly because I'm not too familiar with the cycle, and I'm uncertain whether I've placed my code at the correct place.
I'm aware there might not be "one answer binds them all" here, I'm accepting the answer that offers most insight.
I put an encrypted element into a cookie usually. That element can be anything, but I generally make it the username.
Then in Global.asax.cs I implement Application_AuthenticateRequest. Each time a page is loaded this method is called by the system. In that method I check the cookie, if it exists, I try to load up the user. If the user loads successfully, then I know I have a logged in user, and I set the current Threads current Principal property to that user.
Once the CurrentPrincipal is set on the current thread you can access that user from your Controller, your View, your Business Layer, anywhere in your execution path.
If I can't use cookies for some reason, then I'll pass it across in ViewData (again encrypted just in case), and store it in hidden variables. Then when Controller::OnActionExecuting runs I do the same work I typically did in AuthenticateRequest (i.e. load the user and put it on the thread).
I have a BaseController class that all my controllers inherit from. It has a "CurrentUser" property that is stored in the session. The full code for my controller has a little more logic for retrieving the user, but this is the basic idea.
public class BaseController : Controller
{
User _currentUser = null;
public User CurrentUser
{
get
{
if (_currentUser == null)
_currentUser = (User)HttpContext.Session["CurrentUser"];
return _currentUser;
}
set
{
_currentUser = value;
HttpContext.Session["CurrentUser"] = value;
}
}
}
}
My models all inherit from a BaseModel class which also has a CurrentUser property.
public class BaseModel
{
public User CurrentUser { get; set; }
}
public class HomeIndexData : BaseModel
{
}
Then my controllers pass the user to the model which allows me to have strongly-typed views.
[HttpGet]
public ActionResult Index()
{
HomeIndexData data = new HomeIndexData();
data.CurrentUser = this.CurrentUser;
return View(data);
}
With this technique, I can also have a strongly-typed master page using BaseModel.
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseModel>" %>
精彩评论