How should I access my ApplicationUser properties from ASP.NET Core Views?

后端 未结 6 1845
小鲜肉
小鲜肉 2020-12-08 15:19

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

6条回答
  •  有刺的猬
    2020-12-08 15:44

    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
    
    
    

    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:

    1. I'm performing the database lookup in a controller (a View Component is a type of controller) and not in a View. Further, the data may well already be in memory as the framework will have already authenticated the request. I haven't looked into whether another database round trip actually happens, and I probably won't bother but if anyone knows, please chime in!
    2. The logic is in one well-defined place; the DRY principle is respected.
    3. I don't have to modify any other View Model.

    Result! I hope someone will find this useful...

提交回复
热议问题