使用Identity Framework Core 2插入AspNetUsers表的主键异常

时间:2018-02-20 21:55:21

标签: c# entity-framework-core

我只是在我的应用程序中设置了与Identity Framework Core 2.0.1的基本集成。我已根据本文(https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-primary-key-configuration?tabs=aspnetcore2x)将IdentityUser配置为使用INT而不是STRING作为其主键。

我首先使用代码创建一个通过初始迁移创建的空白数据库。

我遇到的问题是,当我创建一个用户(我使用邮差)时,我得到了以下异常:

Cannot insert explicit value for identity column in table 'AspNetUsers' when IDENTITY_INSERT is set to OFF.

当它传递给UserManager.CreateAsync时我检查了appUser.Id的值,它肯定是= 0(这是Int属性的CLR默认值)

如果我将AppUser配置为使用String作为主键(默认设置),则Id列未设置为标识列,并且我没有收到任何错误 - 创建用户时没有GUID作为ID的问题由Identity框架内部生成。

来自邮递员:

{
    "email":"someemail@comcast.net",
    "password":"Password123",
    "firstName":"Alex",
    "lastName":"Florin",
    "userName":"aflorin"
}

AppUser.cs

using Microsoft.AspNetCore.Identity;

namespace Driver.Models.Entities
{
    public class AppUser : IdentityUser<int>
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

AppRole.cs

using Microsoft.AspNetCore.Identity;

namespace Driver.Models.Entities
{
    public class AppRole : IdentityRole<int>    {

    }
}

IAppUserRepository.cs

using System.Threading.Tasks;

namespace Driver.Repositories
{
    public interface IAppUserRepository<AppUser> 
    {
        Task Create(AppUser appUser, string password);
    }
}

AppUserRepository.cs

using Driver.DBContext;
using Driver.Models.Entities;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;


namespace Driver.Repositories
{
    public class AppUserRepository : IAppUserRepository<AppUser>
    {

        private UserManager<AppUser> _userManager;
        protected DriverDbContext _dbContext;

        public AppUserRepository(UserManager<AppUser> userManager, DriverDbContext dbContext)
        {
            _userManager = userManager;
            _dbContext = dbContext;
        }

        public async Task Create(AppUser appUser, string password)
        {
            var result = await _userManager.CreateAsync(appUser, password);

            //ToDo: if (!result.Succeeded) { }

            await _dbContext.SaveChangesAsync();
        }

    }
}

AccountsController.cs

using Driver.Models.Entities;
using Driver.ViewModels.Identity;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Driver.Repositories;

namespace Driver.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class AccountsController : Controller
    {
        private IAppUserRepository<AppUser> _appUserRepository;

        public AccountsController(UserManager<AppUser> userManager, IAppUserRepository<AppUser> appUserRepository)
        {
            _appUserRepository = appUserRepository;
        }

        [HttpPost]
        public async Task<IActionResult> Create([FromBody]RegistrationViewModel registrationVM)
        {
            if (registrationVM == null)
            {
                return BadRequest();
            }

            var appUser = Mapper.Map<AppUser>(registrationVM);

            await _appUserRepository.Create(appUser, registrationVM.Password);

            return CreatedAtAction("Create", new { id = appUser.Id }, Mapper.Map<RegistrationViewModel>(appUser));
        }
    }
}

RegistrationViewModel.cs

namespace Driver.ViewModels.Identity
{
    public class RegistrationViewModel
    {
        public string Email { get; set; }
        public string Password { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string UserName { get; set; }
    }
}

从Startup.cs配置服务

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DriverDbContext>(options => options.UseSqlServer(_config.GetConnectionString("DriverDBConnection")));

    services.AddSingleton<IJwtFactory, JwtFactory>();

    services.TryAddTransient<IHttpContextAccessor, HttpContextAccessor>();

    services.AddIdentity<AppUser, IdentityRole<int>>()
        .AddEntityFrameworkStores<DriverDbContext>()
        .AddDefaultTokenProviders();

    var settings = _config.GetSection("Authentication").Get<AuthenticationAppSettings>();

    // Configure JwtIssuerOptions
    services.Configure((Models.JwtIssuerOptions options) =>
    {
        options.Issuer = settings.JwtIssuerOptions.Issuer;
        options.Audience = settings.JwtIssuerOptions.Audience;
        options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
    });

    // Specify the validation parameters to dictate how we want received tokens validated
    var tokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = settings.JwtIssuerOptions.Issuer,

        ValidateAudience = true,
        ValidAudience = settings.JwtIssuerOptions.Audience,

        ValidateIssuerSigningKey = true,
        IssuerSigningKey = _signingKey,

        RequireExpirationTime = false,
        ValidateLifetime = true,
        ClockSkew = TimeSpan.Zero
    };


    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

    }).AddJwtBearer(configureOptions =>
    {
        configureOptions.ClaimsIssuer = settings.JwtIssuerOptions.Issuer;
        configureOptions.TokenValidationParameters = tokenValidationParameters;
        configureOptions.SaveToken = true;
    });

    // Create an authorization claim policy to guard API controllers and actions
    services.AddAuthorization(options =>
    {
        options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
    });

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings
        options.Password.RequireDigit = settings.Password.RequiredDigit;
        options.Password.RequiredLength = settings.Password.RequiredLength;
        options.Password.RequireNonAlphanumeric = settings.Password.RequireNonAlphanumeric;
        options.Password.RequireUppercase = settings.Password.RequireUppercase;
        options.Password.RequireLowercase = settings.Password.RequireLowercase;
        options.Password.RequiredUniqueChars = settings.Password.RequiredUniqueChars;

        // Lockout settings
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(settings.Lockout.DefaultLockoutTimeSpan);
        options.Lockout.MaxFailedAccessAttempts = settings.Lockout.MaxFailedAccessAttempts;
        options.Lockout.AllowedForNewUsers = settings.Lockout.AllowedForNewUsers;

        // User settings
        options.User.RequireUniqueEmail = settings.User.RequireUniqueEmail;
    });


    services.AddMvc().AddJsonOptions(
        options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    );

    services.AddAutoMapper(typeof(Startup));

    services.AddScoped<ICompanyRepository, CompanyRepository>();
    services.AddScoped<ILookupRepository, LookupRepository>();
    services.AddScoped<IManagerRepository, ManagerRepository>();
    services.AddScoped<IAppUserRepository<AppUser>, AppUserRepository>();

}

我的DbContext的类声明行(我没有在AppUser实体上进行任何自定义配置):

public class DriverDbContext : IdentityDbContext<AppUser, AppRole, int>

0 个答案:

没有答案