I\'m working on an ASP.Net vNext / MVC6 project. I\'m getting to grips with ASP.Net Identity.
The ApplicationUser
class is apparently where I\'m suppose
OK, here's how I eventually did it. I used a new feature in MVC6 called View Components. These work a bit like partial views, but they have a "mini controller" associated with them. The View Component is a lightweight controller that doesn't participate in model binding, but it can have something passed to it in constructor parameters, possibly using dependency injection and then it can construct a View Model and pass that to a partial view. So, for example, you can inject a UserManager
instance into the View Component, use that to retrieve the ApplicationUser
object for the current user and pass that to the partial view.
Here's what it looks like in code. First, the View Component, which lives in /ViewComponents
directory:
public class UserProfileViewComponent : ViewComponent
{
readonly UserManager userManager;
public UserProfileViewComponent(UserManager userManager)
{
Contract.Requires(userManager != null);
this.userManager = userManager;
}
public IViewComponentResult Invoke([CanBeNull] ClaimsPrincipal user)
{
return InvokeAsync(user).WaitForResult();
}
public async Task InvokeAsync([CanBeNull] ClaimsPrincipal user)
{
if (user == null || !user.IsSignedIn())
return View(anonymousUser);
var userId = user.GetUserId();
if (string.IsNullOrWhiteSpace(userId))
return View(anonymousUser);
try
{
var appUser = await userManager.FindByIdAsync(userId);
return View(appUser ?? anonymousUser);
}
catch (Exception) {
return View(anonymousUser);
}
}
static readonly ApplicationUser anonymousUser = new ApplicationUser
{
Email = string.Empty,
Id = "anonymous",
PhoneNumber = "n/a"
};
}
Note that the userManager
constructor parameter is injected by the MVC framework; this is configured by default in Startup.cs
in a new project so there's no configuration to be done.
The view component is invoked, unsurprisingly, by calling the Invoke
method or the asynchronous version of it. The method retrieves an ApplicationUser
if possible, otherwise it uses an anonymous user with some safe defaultspreconfigured. It uses this user to its partiel view s the view model. The view lives in /Views/Shared/Components/UserProfile/Default.cshtml
and starts like this:
@model ApplicationUser
@Html.GravatarImage(Model.Email, size:80)
@Model.UserName
@Model.PhoneNumber
And finally, I invoke this from within my _Navigation.cshtml
partial view like so:
@await Component.InvokeAsync("UserProfile", User)
This meets all of my original requirements, because:
Result! I hope someone will find this useful...