我想在母版页中包含的局部视图中显示用户的屏幕名称。这是经典的“登录”/“欢迎John Smith!退出”场景。用户的屏幕名称与User.Identity.Name
不同,需要查找数据库,即
AppUser currentUser = appRepository.GetAppUser(User.Identity.Name);
string screenName = currentUser.ScreenName;
这不会在视图中起作用 - 没有对'appRepository'的引用,并且视图不应该真正绕过进行数据库调用。我该如何设置它以便将屏幕名称从控制器传递给视图?
我的所有控制器都继承自BaseController
。我尝试在ViewData["CurrentAppUser.ScreenName"]
类的构造函数中设置BaseController
,但此时尚未填充User对象。 (如果相关,我将OpenID与DotNetOpenAuth一起使用。)我可以在每个控制器的每个操作方法中设置它,但这将是非常难看的。
我还尝试在用户登录时设置会话变量,但即使会话结束,用户也似乎可以保持登录状态。当他们再次回来时,他们仍然登录,但会话变量未设置。
有什么想法吗?
答案 0 :(得分:2)
我建议您使用Html.Action。因此,您一如既往地定义视图模型:
public class UserInfoViewModel
{
public string ScreenName { get; set; }
}
然后是控制器:
public class UserInfoController: Controller
{
private readonly IUsersRepository _repository;
public UserInfoController(IUsersRepository repository)
{
_repository = repository;
}
// Use this attribute if you want to restrict direct access
// to this action.
[ChilActionOnly]
public ActionResult Index()
{
var model = _repository.GetUserInfo(User.Identity.Name);
return PartialView(model);
}
}
相应的局部视图:
@model UserInfoViewModel
<div>Hello @Html.DisplayFor(x => x.ScreenName )</div>
最后在您的母版页中(无论使用哪个控制器渲染视图)都包含部分:
@Html.Action("Index", "UserInfo")
或(Html.RenderPartial
执行相同操作但不返回结果但直接将其写入输出流中:
@{Html.ActionPartial("Index", "UserInfo");}
为了避免在每次获取用户屏幕名称的请求中访问数据库,对此进行进一步改进将是将其缓存在某处:session,cookie,...
因此不需要基本控制器和ViewData
。获取用户屏幕名称的逻辑与主MVC管道完全分离,并作为窗口小部件嵌入。