我应该如何访问我的ApplicationUser性质从我的MVC 6次内? [英] How should I access my ApplicationUser properties from within my MVC 6 Views?

查看:182
本文介绍了我应该如何访问我的ApplicationUser性质从我的MVC 6次内?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个ASP.Net vNext / MVC6项目。我越来越与ASP.Net身份交手。

I'm working on an ASP.Net vNext / MVC6 project. I'm getting to grips with ASP.Net Identity.

ApplicationUser 类显然是在那里我应该添加任何额外的用户属性,这可以与实体框架和我的其他属性得到存储在数据库中预期

The ApplicationUser class is apparently where I'm supposed to add any additional user properties, and this works with Entity Framework and my additional properties get stored in the database as expected.

然而,问题是当我想从我的观点中访问在当前登录用户的详细信息。具体来说,我有一个 _loginPartial.cshtml 中,我要检索和显示用户的Gravatar图标,为此我需要的电子邮件地址。

However, the problem comes when I want to access the details of the currently logged in user from within my views. Specifically, I have a _loginPartial.cshtml in which I want to retrieve and display the user's Gravatar icon, for which I need the email address.

剃刀查看基类有一个用户属性,它是一个 ClaimsPrincipal 。如何从这个用户去属性回到我的 ApplicationUser ,找回我的自定义属性?

The Razor View base class has a User property, which is a ClaimsPrincipal. How do I go from this User property back to my ApplicationUser, to retrieve my custom properties?

请注意,我不问如何找到信息;我知道如何寻找一个 ApplicationUser User.GetUserId()值。这更多的是关于如何明智地处理这个问题的问题。具体来说,我不想:

Note that I'm not asking how to find the information; I know how to lookup an ApplicationUser from the User.GetUserId() value. This is more a question about how to approach this problem sensibly. Specifically, I don't want to:


  • 从我的观点中执行任何类型的数据库查询的(关注点分离)

  • 有逻辑添加到每个控制器来检索当前用户的详细信息(DRY原则)

  • 有一个用户属性添加到每个视图模型。

这似乎是一个横切关注点是应该有一个集中的标准溶液,但我觉得我缺少的一块拼图。什么是从视图中获得那些自定义用户属性的最佳方法?

This seems like a 'cross-cutting concern' that ought to have a centralized standard solution, but I feel like I'm missing a piece of the jigsaw puzzle. What is the best way to get at those custom user properties from within views?

请注意:看来,MVC团队已通过确保UserName属性总是被设置为用户的电子邮件地址,整齐地避免了需要他们执行此查询来获取用户的侧加强的项目模板内这个问题电子邮件地址!这似乎是一个有点作弊的,我和我的解决方案的用户的登录名可能是也可能不是他们的电子邮件地址,所以我不能依赖于伎俩(我怀疑会有我以后需要访问其他属性)。

Note: It seems that the MVC team has side-stepped this issue within the project templates by ensuring that the UserName property is always set to the user's email address, neatly avoiding the need for them to perform this lookup to get the user's email address! That seems like a bit of a cheat to me and in my solution the user's login name may or may not be their email address, so I can't rely on that trick (and I suspect there will be other properties I need to access later).

推荐答案

OK,下面是我最终做到了。我以前在MVC6一项新功能名为视图组件。这些工作有点像局部视图,但他们有一个微型控制器的与它们相关联。视图组件是不参与模型绑​​定一个轻量级的控制器,但可以有东西传递给它的构造函数的参数,可能使用依赖注入,然后可以构造一个视图模型和它传递给一个局部视图。因此,例如,你可以注入一个的UserManager 实例到视图组件,使用以检索 ApplicationUser 对象当前用户并传递到局部视图。

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.

下面是它看起来像在code。首先,查看组件,它生活在 / ViewComponents 目录:

Here's what it looks like in code. First, the View Component, which lives in /ViewComponents directory:

public class UserProfileViewComponent : ViewComponent
    {
    readonly UserManager<ApplicationUser> userManager;

    public UserProfileViewComponent(UserManager<ApplicationUser> userManager)
        {
        Contract.Requires(userManager != null);
        this.userManager = userManager;
        }

    public IViewComponentResult Invoke([CanBeNull] ClaimsPrincipal user)
        {
        return InvokeAsync(user).WaitForResult();
        }

    public async Task<IViewComponentResult> 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"
        };
    }

请注意,的UserManager 构造函数的参数是由MVC框架注入;这是默认的一个新项目配置在 Startup.cs 所以没有做配置。

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.

视图组件被调用时,勿庸置疑,通过调用调用方法或者它的异步版本。该方法检索 ApplicationUser 如果可能的话,否则,使用一些安全的默认设置preconfigured匿名用户。它使用此用户对其partiel视图S中的视图模型。视图住在 /Views/Shared/Components/UserProfile/Default.cshtml 并开始是这样的:

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

<div class="dropdown profile-element">
    <span>
        @Html.GravatarImage(Model.Email, size:80)
    </span>
    <a data-toggle="dropdown" class="dropdown-toggle" href="#">
        <span class="clear">
            <span class="block m-t-xs">
                <strong class="font-bold">@Model.UserName</strong>
            </span> <span class="text-muted text-xs block">@Model.PhoneNumber <b class="caret"></b></span>
        </span>
    </a>

</div>

最后,我调用这个从我的 _Navigation.cshtml 部分观点中,像这样:

@await Component.InvokeAsync("UserProfile", User)

这符合所有的我原来的要求,因为:

This meets all of my original requirements, because:


  1. 我在控制器中进行数据库查询(View组件是一个类型的控制器)的视图,而不是。此外,数据可能已经在存储器中作为框架将已认证的请求。我没有看过到另一个数据库往返是否实际发生的情况,我可能不会打扰,但如果有谁知道,请附和!

  2. 的逻辑是在一个定义良好的地方; DRY原则得到尊重。

  3. 我没有修改任何其他视图模型。

结果!我希望有人会发现这很有用...

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

这篇关于我应该如何访问我的ApplicationUser性质从我的MVC 6次内?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆