在控制器构造函数中使用User.Identity.Name定义用户

8
对于我要与用户账户进行交互的操作,我想在控制器调用任何操作时创建一个“TheUser”对象,并将该对象添加到“ViewData [“TheUser”]”中。
如果用户已登录,则从数据库中获取用户信息,否则,“TheUser”对象将为空。
我尝试在控制器构造函数中访问“User.Identity.Name”,但在调用任何操作之前它并未被创建。
我正在查看自定义授权过滤器,但这些过滤器无法让我创建“TheUser”对象并将其存储在ViewData中。
这是我想要实现的简短片段:
[Authorize]
public class HomeController : Controller
{
    User TheUser;

    public HomeController()
    {
        TheUser = User.Identity.IsAuthenticated ? UserRepository.GetUser(User.Identity.Name) : null;

        ViewData["TheUser"] = TheUser;  
    }
}

这个答案对我在MVC3方面有所帮助 http://stackoverflow.com/a/1506311/511438 - Valamas
4个回答

18

我创建了一个自定义的基础控制器类,并添加了一个名为“CurrentUser”的属性。

在Initialize方法中,我编写了获取用户并将其添加到控制器的ViewData和“CurrentUser”属性的逻辑。

我的控制器继承了自定义的基础控制器类,这样我就可以在控制器的任何地方引用“CurrentUser”变量:

public class CustomControllerClass : Controller
{
    public User CurrentUser { get; set; }

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        if (requestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            string userName = requestContext.HttpContext.User.Identity.Name;
            CurrentUser = UserRepository.GetUser(userName);
        }

        ViewData["CurrentUser"] = CurrentUser;                
    }
}

当我从BaseController继承我的Controller时,执行BaseController的Execute方法后,所有的Web请求都停止了,并且不会进入Action方法。在浏览器中显示一个空白页面。我们还需要做更多的事情来运行它吗? - teenup
Puneet,请看一下我的编辑。我最初的答案是针对ASP.NET MVC 1的。我更新了它,以覆盖Initialize方法,因为这是在MVC 2和3中执行此类操作的接受位置。 - Omar
非常感谢,我真的很感激这个。寻找了很长时间,你的答案简洁明了。 - j_walker_dev

5

我使用构造方法类似地设置了我的基础控制器,并且我能够以以下方式读取此用户信息。注意:我仅存储UserId,而不是User对象,但我的代码的重点是展示如何在构造方法中获取所需信息。

public abstract class BaseController : Controller
{
    int _UserId = 0;

    public int UserId
    {
        get { return _UserId; }
        set { _UserId = value; }
    }

    public BaseController()
    {
        var userFromAuthCookie = System.Threading.Thread.CurrentPrincipal;

        if (userFromAuthCookie != null  && userFromAuthCookie.Identity.IsAuthenticated) // && !String.IsNullOrEmpty(userFromAuthCookie.Identity.Name))
        {
            busUser userBO = AceFactory.GetUser();
            string userNameFromAuthCookie = userFromAuthCookie.Identity.Name;
            _UserId = userBO.GetUserIdByUsername(userNameFromAuthCookie);
        }
    }

我也试图使用User.Identity返回用户 - System.Threading.Thread.CurrentPrincipal为我解决了这个问题 - 非常感谢 - wheelibin
System.Threading.Thread.CurrentPrincipal帮助我在实际构造函数中访问了我的用户ID。谢谢。 - Kevin Dark

3
public abstract class YourController : Controller
{
    public YourController()
    {
        var user = System.Threading.Thread.CurrentPrincipal;

        TheUser = User.Identity.IsAuthenticated ? UserRepository.GetUser(user.Identity.Name) : null;

        ViewData["TheUser"] = TheUser;  
    }
}

2
用户是否需要为每个控制器操作实例化,还是只需要实例化特定的操作?
如果您创建一个ActionFilterAttribute,您可以访问Controller上下文。不确定这是否适用于AuthorizationFilters,但您可以尝试类似以下方式:
public class MyCustomFilter: ActionFilterAttribute
{

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.Controller.ViewData["TheUser"] = User.Identity.IsAuthenticated ? UserRepository.GetUser(User.Identity.Name) : null;
        base.OnActionExecuting(filterContext);
    }
}

然后,将其附加到必要的控制器操作中。

TheUser被用于每个操作。令我疑惑的是,尽管[Authorize]确保了用户已经通过认证,我却无法访问User.Identity,但我可以访问ViewData。 - Omar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接