I want to display the user's screen name in a partial view that is contained in a master page. It is the classic "Log In" / "Welcome John Smith! Log Out" scenario. The user's screen name is different to the User.Identity.Name
and requires a database look up, i.e.
AppUser currentUser = appRepository.GetAppUser(User.Identity.Name);
string screenName = currentUser.ScreenName;
This is not going to work from within a view - there is no reference to 'appRepository' and views shouldn't really be going around making database calls anyway. How should I set this up so that the screen name is passed to the view from the controller?
All my controllers inherit from a BaseController
. I tried setting ViewData["CurrentAppUser.ScreenName"]
in the constructor of the of the BaseController
class, but at that point the User object is not populated yet. (I am using OpenID with DotNetOpenAuth if that is relevant.) I could set it in every action method on every controller, but that would be supremely ugly.
I also tried setting a session variable when the user logs on, but it seems a use开发者_StackOverflowr can stay logged in even if the session ends. When they come back again they are still logged in, but the session variable is unset.
Any ideas?
I would recommend you using Html.Action. So as always you start by defining a view model:
public class UserInfoViewModel
{
public string ScreenName { get; set; }
}
then a controller:
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);
}
}
a corresponding partial view:
@model UserInfoViewModel
<div>Hello @Html.DisplayFor(x => x.ScreenName )</div>
finally in your master page (no matter which controller was used to render the view) include the partial:
@Html.Action("Index", "UserInfo")
or (Html.RenderPartial
which does the same but doesn't return the result but writes it directly to the output stream):
@{Html.ActionPartial("Index", "UserInfo");}
A further improvement of this in order to avoid hitting the database on each request for fetching the user screen name would be to cache it somewhere: session, cookie, ...
So no need of base controllers and ViewData
. The logic of getting the user screen name is completely separate from the main MVC pipeline and embedded as a widget.
精彩评论