简体   繁体   English

评估ASP.NET 5 / MVC6 Identity Custom Profile数据属性

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

I have made a sample web app named ShoppingList using the asp.net 5 web application template (Mvc6/MVC core/Asp.net-5). 我使用asp.net 5 Web应用程序模板(Mvc6 / MVC core / Asp.net-5)制作了一个名为ShoppingList的示例Web应用程序。 I wanted to extend the user profile with a custom field name DefaultListId. 我想使用自定义字段名称DefaultListId扩展用户配置文件。

The ApplicationUser.cs: 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: 我试过了:

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 严重性代码说明项目文件行抑制状态错误CS7036没有给出与“ UserManager.UserManager(IUserStore,IOptions,IPasswordHasher,IEnumerable>,IEnumerable>,ILookupNormalizer,IdentityErrorDescriber,IServiceProvider,IServiceProvider,ILogProvider)的必需形式参数'optionsAccessor”相对应的参数。 >,IHttpContextAccessor)'ShoppingList.DNX 4.5.1,ShoppingList.DNX Core 5.0 C:\\ Users \\ OleKristian \\ Documents \\ Programmering \\ ShoppingList \\ src \\ ShoppingList \\ Controllers \\ HomeController.cs 15有效

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 严重性代码说明项目文件行抑制状态错误CS1061'UserManager'不包含'FindById'的定义,并且找不到扩展方法'FindById'接受类型为'UserManager'的第一个参数(您是否缺少using指令或程序集参考?)ShoppingList.DNX 4.5.1,ShoppingList.DNX Core 5.0 C:\\ Users \\ OleKristian \\ Documents \\ Programmering \\ ShoppingList \\ src \\ ShoppingList \\ Controllers \\ HomeController.cs 20有效

You should not instantiate your own UserManager , like ever. 您不应UserManager实例化自己的UserManager 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). 这样做实际上非常困难,因为它要求您将大量参数传递给构造函数(而且大多数事情也很难正确设置)。

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. ASP.NET Core广泛使用了依赖项注入,因此您应该以自动接收用户管理器的方式来设置控制器。 That way, you don't have to worry about creating the 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. 但是,为此,您首先需要设置ASP.NET身份以真正了解您的ApplicationUser ,并将其用于存储用户身份。 To do that, you need to modify the Startup class. 为此,您需要修改Startup类。 In the ConfigureServices method, you need to change the AddIdentity call to make it reference your actual types: 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). IdentityRole在此是指ASP.NET Identity使用的标准角色类型(因为您不需要自定义角色)。 As you can see, we also reference a ApplicationDbContext there which is the entity framework database context for your modified identity model; 如您所见,我们还引用了ApplicationDbContext ,它是您修改后的身份模型的实体框架数据库上下文; so we need to set up that one too. 所以我们也需要设置一个。 In your case, it could just look like this: 在您的情况下,它可能看起来像这样:

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. 这将确保ApplicationUser实体实际上已正确存储在数据库中。 We're almost done, but we now just need to tell Entity Framework about this database context as well. 我们差不多完成了,但是我们现在只需要告诉Entity Framework这个数据库上下文。 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. 因此,再次在Startup类的ConfigureServices方法中,确保调整AddEntityFramework调用以也设置ApplicationDbContext数据库上下文。 If you have other database contexts, you can just chain these: 如果您还有其他数据库上下文,则可以将它们链接在一起:

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. 现在,Entity Framework知道了新的用户实体并将其正确映射到数据库(包括您的新属性),而ASP.NET Identity也知道了您的用户模型,并将其用于所有用户模型,您可以使用UserManager注入控制器(或服务或任何其他东西)来做事。


As for your second error, you get this because the user manager does not have a FindById method; 至于第二个错误,您得到这个是因为用户管理器没有FindById方法。 it only as a FindByIdAsync method. 它仅作为FindByIdAsync方法。 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. 在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. 大多数都保持不变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM