InvalidOperationException:无法在'ApplicationUser'上配置密钥,因为它是派生类型

时间:2019-07-12 20:55:00

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

当我创建一个帐户时,它可以正常工作,没有错误,并且注销正常。但是,当我尝试重新登录时出现此错误:

  

“无法为'IdentityUser'创建DbSet,因为该类型不包含在上下文模型中。”

我忽略了它,因为我想从事其他一些工作。当我使用种子方法添加UserRoles时,它首先运行良好,我猜没有任何错误。但是,当我执行登录操作时,出现了下一个错误:

  

“ InvalidOperationException:无法在'ApplicationUser'上配置密钥,因为它是派生类型。必须在根类型'IdentityUser'上配置密钥。如果您不打算将'IdentityUser'包括在模型中,请确保它不包含在上下文的DbSet属性中,在对ModelBuilder的配置调用中引用,在模型中包含的类型的导航属性中引用。”

我删除了旧数据库并删除了迁移。当我尝试添加迁移(添加迁移用户)时,出现下一个错误: “无法在'ApplicationUser'上配置密钥,因为它是派生类型。必须在根类型'IdentityUser'上配置密钥。如果您不打算将'IdentityUser'包括在模型中,请确保它是没有包含在您上下文的DbSet属性中,没有在对ModelBuilder的配置调用中引用,或者从模型中包含的类型的导航属性中引用。”

我正在尝试添加自定义身份和UserRoles,我遵循了有关如何向您的IdentityUser添加自定义数据的教程,而一位老师给了我们有关如何添加UserRoles的教程。

我是初学者,将.net core 2.2 mvc与单个用户帐户一起使用。

ApplicationDbContext.cs:

using System;
using System.Collections.Generic;
using System.Text;
using application.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace application.Data
{
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        public virtual DbSet<IdentityUser> ApplicationUser {get; set;}
        public new DbSet<application.Models.Update> Update { get; set; }
    }
}

Seed.cs:

using System;
using System.Collections.Generic;
using System.Text;
using application.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace application.Data
{
    public class Seed
    {
        public static void SeedUsers(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
        {
            if (roleManager.FindByNameAsync("Admin").Result == null)
            {
                IdentityRole role = new IdentityRole { Name = "Admin" };
                roleManager.CreateAsync(role).Wait();
            }

            if (userManager.FindByEmailAsync("admin@admin.com").Result == null)
            {
                ApplicationUser user = new ApplicationUser
                {
                    FirsName    = "Admin",
                    LastName    = "Admin", 
                    Email       = "admin@admin.com"
                };

                IdentityResult result = userManager.CreateAsync(user, "AdminTest420").Result;

                if (result.Succeeded)
                {
                    userManager.AddToRoleAsync(user, "Admin").Wait();
                }
            }
        }
    }
}

ApplicationUser.cs:

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

namespace application.Models
{
    public class ApplicationUser : IdentityUser
    {
        public string FirsName { get; set; }
        public string LastName { get; set; }
    }
}

StartUp.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using application.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using application.Models;

namespace application
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddDefaultIdentity<IdentityUser>()
                .AddDefaultUI(UIFramework.Bootstrap4)
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddIdentityCore<ApplicationUser>()
                .AddRoles<IdentityRole>()
                .AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders()
                .AddDefaultUI();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();


            app.UseAuthentication();
            //Seed.SeedUsers(userManager, roleManager);

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                  name: "Admin",
                  template: "{area:exists}/{controller=AdminHome}/{action=Index}/{id?}");
            });
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您的问题是由public virtual DbSet<IdentityUser> ApplicationUser {get; set;}引起的。

对于ApplicationUser,您可以通过AspNetUsers访问_context.Users表。

要自定义身份,请遵循此Identity model customization in ASP.NET Core

答案 1 :(得分:0)

我通过将IdentityUser的所有用法替换为ApplicationUser来解决了同一问题。在IdentityUser继承ApplicationUser之后,您应该在代码中的任何地方使用ApplicationUser。只要确保您没有在类或视图中引用IdentityUser。

实际上您不需要此行

public virtual DbSet<IdentityUser> ApplicationUser {get; set;}

只需阅读本文custome user data

您可以通过DI访问AplicationUser

public class MyController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;

        public MyController(
            UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }