【问题标题】:Accssing ASP.NET 5 / MVC6 Identity Custom Profile data properties访问 ASP.NET 5 / MVC6 身份自定义配置文件数据属性
【发布时间】:2016-05-24 23:56:57
【问题描述】:

我使用 asp.net 5 Web 应用程序模板 (Mvc6/MVC core/Asp.net-5) 制作了一个名为 ShoppingList 的示例 Web 应用程序。我想使用自定义字段名称 DefaultListId 扩展用户配置文件。

ApplicationUser.cs:

namespace ShoppingList.Models
{
    // Add profile data for application users by adding properties to the ApplicationUser class
    public class ApplicationUser : IdentityUser
    {
        public int DefaultListId { get; set; }
    }
}

在家庭控制器中,我想访问为此属性存储的数据。我试过了:

namespace ShoppingList.Controllers
{
    public class HomeController : Controller
    {
       private UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

        public IActionResult Index()
        {
           var userId = User.GetUserId();
           ApplicationUser user = userManager.FindById(userId);

            ViewBag.UserId = userId;
            ViewBag.DefaultListId = user.DefaultListId;

            return View();
        }
    //other actions omitted for brevity

但是我收到以下错误:

严重性代码描述项目文件行抑制状态 错误 CS7036 没有给出对应于 所需的形式参数“optionsAccessor”的 'UserManager.UserManager(IUserStore, IOptions, IPasswordHasher, IEnumerable>, IEnumerable>,ILookupNormalizer, IdentityErrorDescriber, IServiceProvider, ILogger>, IHttpContextAccessor)' ShoppingList.DNX 4.5.1, ShoppingList.DNX 核心 5.0 C:\Users\OleKristian\Documents\Programmering\ShoppingList\src\ShoppingList\Controllers\HomeController.cs 15 活动

还有……

严重性代码描述项目文件行抑制状态 错误 CS1061 'UserManager' 不包含 'FindById' 的定义并且没有扩展方法 'FindById' 接受 可以找到“UserManager”类型的第一个参数 (您是否缺少 using 指令或程序集 参考?) ShoppingList.DNX 4.5.1,ShoppingList.DNX 核心 5.0 C:\Users\OleKristian\Documents\Programmering\ShoppingList\src\ShoppingList\Controllers\HomeController.cs 20 活动

【问题讨论】:

    标签: c# asp.net-core-mvc


    【解决方案1】:

    您不应像以往一样实例化您自己的UserManager。而且实际上很难做到这一点,因为它需要您向构造函数传递大量参数(而且大多数这些东西也很难正确设置)。

    ASP.NET Core 广泛使用依赖注入,因此您只需将控制器设置为自动接收用户管理器即可。这样,您就不必担心创建用户管理器:

    public class HomeController : Controller
    {
        private readonly UserManager<ApplicationUser> userManager;
    
        public HomeController (UserManager<ApplicationUser> userManager)
        {
            this.userManager = userManager;
        }
    
        // …
    }
    

    但是,为了做到这一点,您首先需要设置 ASP.NET 身份以实际了解您的ApplicationUser 并使其使用 来存储您的用户身份。为此,您需要修改 Startup 类。在ConfigureServices 方法中,您需要更改AddIdentity 调用以使其引用您的实际类型:

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
    

    IdentityRole 这里指的是 ASP.NET Identity 使用的标准角色类型(因为您不需要自定义角色类型)。如您所见,我们还引用了ApplicationDbContext,它是您修改后的身份模型的实体框架数据库上下文;所以我们也需要设置那个。在你的情况下,它可能看起来像这样:

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
    
            // here you could adjust the mapping
        }
    }
    

    这将确保ApplicationUser 实体实际上正确存储在数据库中。我们几乎完成了,但我们现在只需要告诉 Entity Framework 这个数据库上下文。所以再次在Startup 类的ConfigureServices 方法中,确保调整AddEntityFramework 调用以设置ApplicationDbContext 数据库上下文。如果你有其他数据库上下文,你可以链接这些:

    services.AddEntityFramework()
        .AddSqlServer()
        .AddDbContext<IdentityContext>(opts => opts.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]))
        .AddDbContext<DataContext>(opts => opts.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
    

    就是这样!现在 Entity Framework 知道新的用户实体并将其正确映射到数据库(包括您的新属性),并且 ASP.NET Identity 也知道您的用户模型并将使用该模型来完成它所做的一切,您可以拥有 @ 987654337@ 注入控制器(或服务,或其他)来做事。


    至于你的第二个错误,你得到这个是因为用户管理器没有FindById 方法;它仅作为FindByIdAsync 方法。实际上,您会在 ASP.NET Core 的很多地方看到这一点,即只有异步方法,因此接受它并开始使您的方法也异步。

    在您的情况下,您需要像这样更改 Index 方法:

    // method is async and returns a Task
    public async Task<IActionResult> Index()
    {
        var userId = User.GetUserId();
    
        // call `FindByIdAsync` and await the result
        ApplicationUser user = await userManager.FindByIdAsync(userId);
    
        ViewBag.UserId = userId;
        ViewBag.DefaultListId = user.DefaultListId;
    
        return View();
    }
    

    如您所见,使方法异步不需要很多更改。大部分都保持不变。

    【讨论】:

    • 非常感谢您对我的问题提供了一个写得很好的和有教育意义的答案。我不得不对代码进行较小的调整,但是在工作之后,它与模板中的现有 ApplicationDbContext 一起工作就像一个魅力: services.AddEntityFramework().AddSqlServer() .AddDbContext(options => options.UseSqlServer(Configuration[ "Data:DefaultConnection:ConnectionString"])) .AddDbContext(opts => opts.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
    • @poke..很好的答案,通常看不到这样的细节......在会话中的 ApplicationUser 类中存储用户配置文件数据的最佳方式是什么。我目前正在使用 basecontroller 类,但该代码在每个操作上都执行。我应该在他们登录时检索一次,然后通过某种方式在每个视图中访问它。
    • @dinotom 根据这​​是什么类型的信息,您应该考虑将其放入声明中。这样,您可以在任何地方访问它们,而无需从数据库中检索用户。但可以肯定的是,您也可以为此使用会话数据。
    • @poke...是的,我目前正试图弄清楚如何做到这一点,但没有到达那里
    • @dinotom 如果您最终无法自己弄清楚,请随意创建一个关于它的新问题,突出显示您到目前为止所学到的知识,您进行了哪些尝试以及这些尝试是如何失败的出去。也请随时 ping 我,这样我就可以看一下了 :)
    猜你喜欢
    • 2010-10-29
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多