如何增加Asp.Net Core生成的模板网站中用户信息表中的列(AspNetUsers)

环境:

1.VS2015 Community 14.0.25431.01 Update 3;

2.其他环境(具体哪一个影响不太清楚,都列在这儿)

使用的系统模板

利用系统提供的模板,并选择个人身份验证。如图:

问题:

模板提供的身份认证数据库中的AspNetUsers表,需要根据需要增加列。以下图为例,绿色框中的列都是模板默认的,我要增加一列(以Test为例)。

解决过程:

刚刚接触MVC、EF的概念,不知道如何操作。查阅了大量资料后发现,网上大部分类似内容都是基于mvc3的,最后还是在stackoverflow上找到一篇(中英文附后)。

但是一步一步按图索骥做下来,在AspNetUsers表中就是加不上Test列,其中还遇到一些错误,例如:几个地方显示使用的方法错误。

最后发现,该例子是基于asp.net 5/6的,许多需要添加的内容模板中已经有了,考虑是不是asp.net core有一些变化。

于是,直接将Test属性直接添加到ApplicationUser中去,发现问题解决了。

原来与之前考虑的一样,asp.net core已经将所需的所有内容都已经考虑好了,不需要做其他的修改。还有,这个版本与之前5/6版本几个方法发生了变化,所以出现了找不到方法的错误(已经标注到附录例子中了)。

我的具体代码如下:(Models/ApplicationUser.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;

namespace Test.Models
{
    // Add profile data for application users by adding properties to the ApplicationUser class
    public class ApplicationUser : IdentityUser
    {
        public string Test { get; set; }//之前该行是空白
    }
}

附:stackoverflow的例子

Accssing ASP.NET 5 / MVC6 Identity Custom Profile data properties

ASP.NET 5 / mvc6身份自定义配置文件数据属性

I have made a sample web app named ShoppingList using the asp.net 5 web application template (Mvc6/MVC core/Asp.net-5). I wanted to extend the user profile with a custom field name DefaultListId.

我做了一个简单的网页应用,该应用使用asp.net 5 网络应用模板(Mvc6/MVC Core/Asp.net 5)。我想扩展用户配置文件,增加客户名称字段(DefaultListID)。

The 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; }
    }
}

In the home controller I would like to access the data stored for this property. I tried:

在home控制器中,我想使用该属性,我做了如下尝试:

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

However I get the following errors:

但是,我得到错误信息如下:

Severity Code Description Project File Line Suppression State Error CS7036 There is no argument given that corresponds to the required formal parameter ‘optionsAccessor‘ of ‘UserManager.UserManager(IUserStore, IOptions, IPasswordHasher, IEnumerable>, IEnumerable>, ILookupNormalizer, IdentityErrorDescriber, IServiceProvider, ILogger>, IHttpContextAccessor)‘ ShoppingList.DNX 4.5.1, ShoppingList.DNX Core 5.0 C:\Users\OleKristian\Documents\Programmering\ShoppingList\src\ShoppingList\Controllers\HomeController.cs 15 Active

And...

还有...

Severity Code Description Project File Line Suppression State Error CS1061 ‘UserManager‘ does not contain a definition for ‘FindById‘ and no extension method ‘FindById‘ accepting a first argument of type ‘UserManager‘ could be found (are you missing a using directive or an assembly reference?) ShoppingList.DNX 4.5.1, ShoppingList.DNX Core 5.0 C:\Users\OleKristian\Documents\Programmering\ShoppingList\src\ShoppingList\Controllers\HomeController.cs 20 Active

回答:

You should not instantiate your own UserManager, like ever. And it’s actually pretty hard to do so, since it requires you to pass in a lot of arguments to the constructor (and most of those things are also very difficult to set up properly).

你不应该像以往一样创建你自己的UserManager。它真的很难做到,因为它需要你通过很多参数的构造函数(很多这些里面的事情要正确设置是很困难的)。

ASP.NET Core makes extensive use of dependency injection, so you should just set up your controller in a way that it receives the user manager automatically. That way, you don’t have to worry about creating the user manager:

ASP.NET Core大量使用依赖注入,所以你应该仅通过自动接收user manager来设置控制器。这样,你不必操心创建的user manager:

public class HomeController : Controller
{
    private readonly UserManager<ApplicationUser> userManager;

    public HomeController (UserManager<ApplicationUser> userManager)
    {
        this.userManager = userManager;
    }

    // …
}

However, in order to do that, you first need to set up ASP.NET Identity to actually know about your ApplicationUser and make it be used for storing your user identities. To do that, you need to modify the Startup class. In the ConfigureServices method, you need to change the AddIdentity call to make it reference your actual types:

但为实现这个目的,你首先需要设置ASP.NET Identity,要其知道你的ApplicationUser,再让其可储存你的用户认可信息。要做到这一点,需要修改Startup类。在ConfigureServices方法中,需要修改AddIdentity,以便让它引用所需的实际类型。

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

IdentityRole here refers to the standard role type used by ASP.NET Identity (since you don’t need a custom one). As you can see, we also reference a ApplicationDbContext there which is the entity framework database context for your modified identity model; so we need to set up that one too. In your case, it could just look like this:

这里的IdentityRole指的是ASP.NET Identity使用的标准角色类型(因此你不需要进行自定义)。正如你看到的,我们在这里也引用了ApplicationDbContext,它是为你修改过的identity model而准备的数据库上下文;所以我们也需要进行设置。在你当前的情况下,看起来如下所示:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        // here you could adjust the mapping
    }
}

This will make sure that the ApplicationUser entity is actually stored properly in the database. We’re almost done, but we now just need to tell Entity Framework about this database context as well. So again in the ConfigureServices method of your Startup class, make sure to adjust the AddEntityFramework call to also set up the ApplicationDbContext database context. If you have other database contexts, you can just chain these:

这将确保ApplicationUser实体妥善保存在数据库中。我们几乎完成了,但是现在我们也只需要告诉EF这个数据库的上下文。所以再次在Startup类的Configureservices方法中,确保调整AddEntityFramework也设置了Applicationdbcontext数据库上下文。如果你有其他数据库上下文,你可以反复这样做:

services.AddEntityFramework()//在Asp.Net Core中到不到这个方法,但是可以找到AddEntityFrameWorkAddSqlServer()方法,可能新版本将第一行和第二行的方法合并了
    .AddSqlServer()
    .AddDbContext<IdentityContext>(opts => opts.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]))
    .AddDbContext<DataContext>(opts => opts.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));//也找不到DataContext类

And that’s it! Now Entity Framework knows about the new user entity and properly maps it to the database (including your new property), and ASP.NET Identity also knows about your user model and will use that one for everything it does, and you can have the UserManager injected into controllers (or services, or whatever) to do stuff.

这样,EF就知道了新user实体及其映射到数据库的属性(包括你自定义的新属性);并且ASP.NET也知道了你自定义的user model,并据其做后面所有的事情;你也可将UserManager注入到控制器中(或者服务或其他所有事情)来处理事务了。

You should not instantiate your own UserManager, like ever. And it’s actually pretty hard to do so, since it requires you to pass in a lot of arguments to the constructor (and most of those things are also very difficult to set up properly).

不应该再像以前那样实例化UserManager,并且实际上那样做相当困难,因为这样做需要给构造器传递许多参数(并且许多配置要设置恰当是非常困难的)。

ASP.NET Core makes extensive use of dependency injection, so you should just set up your controller in a way that it receives the user manager automatically. That way, you don’t have to worry about creating the user manager:

ASP.NET Core广泛应用了注入技术,所以你应该仅给控制器设置为自动接收user manager。这样做,你就不必考虑创建user manager了。

public class HomeController : Controller
{
    private readonly UserManager<ApplicationUser> userManager;

    public HomeController (UserManager<ApplicationUser> userManager)
    {
        this.userManager = userManager;
    }

    // …
}

However, in order to do that, you first need to set up ASP.NET Identity to actually know about your ApplicationUser and make it be used for storing your user identities. To do that, you need to modify the Startup class. In the ConfigureServices method, you need to change the AddIdentity call to make it reference your actual types:

然而,为了这样做,你首先需要设置ASP.NET Identity,让它知道你的ApplicationUser,并且让他用于存储你的用户身份认证信息。为了实现这个目的,你需要修改Startup类。在ConfigureServices方法中,你需要修改AddIdentity,让它引用你以及的类型:

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

IdentityRole here refers to the standard role type used by ASP.NET Identity (since you don’t need a custom one). As you can see, we also reference a ApplicationDbContext there which is the entity framework database context for your modified identity model; so we need to set up that one too. In your case, it could just look like this:

这里的IdentityRole指的是ASP.NET Identity标准的角色类型(因为你不需要自定义的角色类型)。这里,我们也引用了ApplicationDbContext,这是用于你修改过的identity模型的数据库上下文;所以,我们也需要做如此设置。针对你的情况,应该是这样:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        // here you could adjust the mapping
    }
}

This will make sure that the ApplicationUser entity is actually stored properly in the database. We’re almost done, but we now just need to tell Entity Framework about this database context as well. So again in the ConfigureServices method of your Startup class, make sure to adjust the AddEntityFramework call to also set up the ApplicationDbContext database context. If you have other database contexts, you can just chain these:

这将确保ApplicationUser实体被适当的储存到数据库中。我们几乎完成了,但现在我们仅需要告诉EF这个数据库上下文。所以再一次在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"]));

And that’s it! Now Entity Framework knows about the new user entity and properly maps it to the database (including your new property), and ASP.NET Identity also knows about your user model and will use that one for everything it does, and you can have the UserManager injected into controllers (or services, or whatever) to do stuff.

这样就完成了。现在EF就知道了新的user实体及其映射到数据库的属性(包含你设置的新属性);同时ASP.NET Identity也知道了你的user模型,接着就会按照该模型做他该做的事情了,这样你就能将UserManager注入到控制器中工作了。



As for your second error, you get this because the user manager does not have a FindById method; it only as a FindByIdAsync method. You will see this actually in a lot of places with ASP.NET Core that there are only asynchronous methods, so embrace it and start making your method asynchronous as well.

关于第二个错误,原因是user manager没有FindById方法,而是仅仅有FindByIdAsync方法。你将在很多使用ASP.NET Core的地方看到,仅有异步方法,所以拥抱并开始使用异步方法吧。

In your case, you would need to change the Index method like this:

在你的情况下,你需要像这样变更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();
}

As you can see, it does not require many changes to make the method asynchronous. Most of it stays just the same.

正如你看到的,使用异步方法不需要太多的变化,很多都是一样的。

原文链接

时间: 2024-11-10 07:37:11

如何增加Asp.Net Core生成的模板网站中用户信息表中的列(AspNetUsers)的相关文章

学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面

学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面 上一篇文章中我们学习了列表页面的结构,@page与@model两个关键Razor指令,以及页面布局应该修改哪里.这一篇文章我们来

Asp.Net Core 生成二维码(NuGet使用QRCoder)

前言 功能:调用web api 接口 1.获取 jpeg 格式的二维码 2.获取中间带有logo 的二维码 3. 下载 jpeg,svg 格式的二维码 需要的NuGet 包: > QRCoder(v1.3.6) > System.Drawing.Common(v4.5.1) 正文 1. 准备项目 创建ASP.NET Core Web Api 应用程序,添加上边说的两个包,并创建Services 文件夹,Services 文件夹中的类如下: 2. 功能:生成jpeg 格式 二维码,通过Api 来

ASP.NET Core 实战:使用 NLog 将日志信息记录到 MongoDB

在项目开发中,日志系统是系统的一个重要组成模块,通过在程序中记录运行日志.错误日志,可以让我们对于系统的运行情况做到很好的掌控.同时,收集日志不仅仅可以用于诊断排查错误,由于日志同样也是大量的数据,通过对这些数据进行集中分析,可以产生极大的价值. 在微服务的系统架构中,由于一个系统会被拆成很多个功能模块,每个模块负责不同的功能,对于日志系统的要求也会更高,比较常见的有 EFLK(ElasticSearch + Filebeat + LogStash + Kibana) 方案,而对于我们这种单体应

[目录] ASP.Net Core 微服务搭建网站

我有一个心愿,可以用最优化的代码完成一个功能丰富的网站. 全文将围绕(1)设计模式  (2)敏捷开发 目的: 结构足够合理,代码足够优美,扩展性.可读性.易维护性做到最优. 以下目录仅为整体思路,后期逐渐完善补充. 1.配置linux环境实现持续集成 2.快速搭建 ASP.net core Web 应用 3.单元测试 4.数据库配置管理 5.服务注册中心 6.网站登录页面 7.用户管理 8.角色管理 9.租户(组织单位)管理(Saas) 10.模块管理 11.菜单(导航)管理 12.主题配置 1

ASP.NET Core使用Angular模板

作为一名程序员,当然要时刻学习..NET Core最为微软大力发展的新技能,当然要在这个天赋树上点一点技能点啦.(第一次发文章,也不知道写点什么( ̄▽ ̄)~*) 最近因为在研究DDD,所以写下这篇文章. 如果您的VS支持.NET Core2.0,那么可以在新建项目中看到添加模板的选项 .NET Core 2.0 SDK 下载地址:https://www.microsoft.com/net/core#windowscmd 安装后重启VS2017就可以看到模板选项了 如果没有安装.NET Core2

开源DDD设计模式框架YMNNetCoreFrameWork第二篇-增加ASp.net core Identity身份认证,JWT身份认证

1.框架增加Identity注册功能 2.框架增加identity登录以后获取JWTtoken 3.请求接口通过token请求,增加验证特性 源代码地址:https://github.com/topgunymn/YMNNetCoreFrameWork JWTtoken生成代码: private string CreateAccessToken(IEnumerable<Claim> claims, TimeSpan? expiration = null) { var now = DateTime

asp.net core 2.1 将控制器抽离到类库中

startup.cs的ConfigureServices中添加: public void ConfigureServices(IServiceCollection services) { var mall = Assembly.Load(new AssemblyName("Mall.Mvc")); //类库的程序集名称 services.AddMvc().AddApplicationPart(mall); } 配置完后确保网站引用类库,就可直接在类库中添加控制器,网站也可以访问到了.

函数模板在c++动态顺序表中的大作用

函数模板提供了一种机制通过它我们可以保留函数定义和函数调用的语义在一个程序位置上封装了一段代码确保在函数调用之前实参只被计算一次. 函数模板提供一个种用来自动生成各种类型函数实例的算法程序员对于函数接口参数和返回类型中的全部或者部分类型进行参数化(parameterize)而函数体保持不变. 函数模板使用注意事项: 1.每个函数模板前边都需要添加模板声明例如:template<typename T> 2.在模板类的使用时,注意其类型改变,例如: template<typename T&g

ASP.NET MVC单点登录(多站点共享用户信息)

一.多站点共享用户信息解决方案: 采用分布式缓存Memcache模拟Session进行用户信息信息共享 1.视图部分 @{ Layout = null; } <!DOCTYPE html> <html> <head> <title>XX商城后台管理系统登录</title> <script type="text/javascript"> if (window.parent.window != window) { wi