2017-02-03 4 views
1

저는 변경 권한이있는 기존 데이터베이스 위에 응용 프로그램을 빌드하고 있습니다. 가능한 한 DB 스키마를 거의 변경하지 마십시오.) 이것은 MySQL 데이터베이스에 대한 사용자 정의 사용자 저장소가있는 Identity 시스템을 사용하려고하는 MVC 5 응용 프로그램입니다.엔티티 유형 ApplicationUser는 현재 컨텍스트에 대한 모델의 일부가 아닙니다. DB 사용자 정의 사용자 저장소가있는 사용자 우선

문제 : 내가 레지스터 방법에 자동 생성 AccountController를 통해 사용자를 등록하려고 다음과 같은 예외가 받고 있어요 :

IdentityResult result = await UserManager.CreateAsync(user, model.Password); 

가 System.InvalidOperationException : 엔티티 타입 ApplicationUser 인을 현재 컨텍스트에 대한 모델의 일부가 아닙니다. System.Data.Entity.Internal.Linq.InternalSet 1.Initialize() at System.Data.Entity.Internal.Linq.InternalSet 1에서 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType (유형 entityType) 에서 System.Data.Entity.Internal.InternalContext.UpdateEntitySetMappingsForType (유형 entityType) 에서 . get_InternalContext() System.Data.Entity.Infrastructure.DbQuery 1.System.Linq.IQueryable.get_Provider() at System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync[TSource](IQueryable 내가 무엇을 시도했다 1 개 소스, 표현 1 predicate, CancellationToken cancellationToken) at System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync[TSource](IQueryable 1 소스, 표현 1 predicate) at Microsoft.AspNet.Identity.EntityFramework.UserStore 6.d__6c.MoveNext()

에서 :

  1. 계정 컨트롤러의 UserManager 인스턴스를 HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();에서 new ApplicationUserManager(new UserStoreService(new Entities()));으로 변경해 보았습니다. 즉각적인 문제를 해결하고 등록 할 수 있습니다. 그러나이 문제는 나중에 암호를 재설정하려고 할 때 나중에 문제를 일으키며 유효하지 않은 사용자 토큰을 얻을 수없는 다른 문제가 발생합니다 (사용자 토큰이 올바르게 작동하는지 확인할 수 있음). HttpContext.GetOwinContext ... UserManager의 버전
  2. 이 같은 자동 생성 된 하나에서 연결 문자열을 변경에 관한 몇 가지 게시물이 :

<add name="Entities" connectionString="metadata=res://*/Models.tools.csdl|res://*/Models.tools.ssdl|res://*/Models.tools.msl;provider=MySql.Data.MySqlClient;provider connection string=&quot;server=localhost;user id=user;password=***;persistsecurityinfo=True;database=db&quot;" providerName="System.Data.EntityClient" />

과 같은 일반적인 연결 문자열은 : <add name="Entities" connectionString="server=localhost;user id=user;password=***;persistsecurityinfo=True;database=db" providerName="MySql.Data.MySqlClient" /> 이것은 의도하지 않은 코드의 첫 번째 예외로 인해 매우 빠르게 폭발합니다. 나선형으로 보였던 길 아래의 몇 가지 다른 문제 (테이블에 키가 선언되지 않은 문제를 수정 한 후). 나는 이것에 대한 제안을하지만이 길을 갈 필요가 없다는 것을 선호한다.

다음은 설정과 관련된 코드입니다. 내가 여기에서 누락 될 수있는 아이디어가 있습니까? 아니면 연결 문자열 아이디어로 이것을 해결할 수있는 유일한 방법입니까?

감사합니다!

설치 기존의 MySQL 데이터베이스에 대해 데이터베이스를 먼저 사용하고 있습니다. this to change the primary key for users to an int과 함께 내 데이터베이스 및 사용자 테이블에 연결할 사용자 지정 사용자 저장소 서비스가 있습니다.

DbContext 설정 (나는 아이덴티티 시스템과 함께 작동하도록 시도에서 자동 생성 된 파일에서 수정 한) :

public partial class Entities : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>// DbContext 
{ 
    public Entities() 
     : base("name=Entities") 
    { 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     throw new UnintentionalCodeFirstException(); 
    } 

    public static Entities Create() 
    { 
     return new Entities(); 
    } 

    //DbSets are here 
} 

ApplicationUser.CS :

public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim> // IUser<int>//IdentityUser 
{ 
    //custom properties are here 

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager) 
    { 

     var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 
     // Add custom user claims here    

     return userIdentity; 
    } 
} 

ApplicationUserManager.cs

public class ApplicationUserManager : UserManager<ApplicationUser, int> 
{ 
    public ApplicationUserManager(IUserStore<ApplicationUser, int> store) 
     : base(store) 
    { } 

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    { 
     var manager = new ApplicationUserManager(new UserStoreService(context.Get<Entities>())); 

     // Configure validation logic for usernames 
     manager.UserValidator = new UserValidator<ApplicationUser, int>(manager) 
     { 
      AllowOnlyAlphanumericUserNames = false, 
      RequireUniqueEmail = true 
     }; 

     // Configure validation logic for passwords 
     manager.PasswordValidator = new PasswordValidator 
     { 
      RequiredLength = 6, 
      RequireNonLetterOrDigit = true, 
      RequireDigit = true, 
      RequireLowercase = true, 
      RequireUppercase = true, 
     }; 

     manager.UserLockoutEnabledByDefault = true; 
     manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 
     manager.MaxFailedAccessAttemptsBeforeLockout = 5; 

     manager.EmailService = new EmailService(); 

     var dataProtectionProvider = options.DataProtectionProvider; 
     if (dataProtectionProvider != null) 
     { 
      manager.UserTokenProvider = 
       new DataProtectorTokenProvider<ApplicationUser, int>(dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromHours(24) }; 
     } 
     return manager; 
    } 
} 

UserStoreService.cs

public class UserStoreService : UserStore<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim> //, IUserStore<ApplicationUser, int>, IUserPasswordStore<ApplicationUser, int>, IUserEmailStore<ApplicationUser, int>, IUserLockoutStore<ApplicationUser, int>, IUserSecurityStampStore<ApplicationUser, int> 
{ 
    private Entities _db; // = new Entities(); 

    public UserStoreService(Entities db) : base(db) 
    { 
     _db = db; 
    } 

    public override Task CreateAsync(ApplicationUser user) 
    { 
     var profile = new ffs_profile { 
      //set props here 
     }; 

     _db.ffs_profile.Add(profile); 
     return _db.SaveChangesAsync(); 
    } 

    public async override Task<ApplicationUser> FindByNameAsync(string userName) 
    { 
     var profile = await _db.ffs_profile.Where(u => u.email == userName).FirstOrDefaultAsync(); 

     ApplicationUser user = null; 
     if (profile != null) 
      user = ToApplicationUser(profile); 

     return user; 
    } 

    private ApplicationUser ToApplicationUser(ffs_profile profile) 
    { 
     return new ApplicationUser 
     { 
      //set properties here 

     }; 
    } 
    public override Task<string> GetPasswordHashAsync(ApplicationUser user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentException("null user"); 
     } 

     return Task.FromResult(user.PasswordHash); 
    } 

    public override Task<bool> HasPasswordAsync(ApplicationUser user) 
    { 
     return Task.FromResult(user.PasswordHash != null); 
    } 

    public override Task SetPasswordHashAsync(ApplicationUser user, string passwordHash) 
    { 
     return Task.Run(() => 
     { 
      if (passwordHash == null) 
       throw new ArgumentNullException("passwordHash"); 
      if (string.IsNullOrWhiteSpace(passwordHash)) 
       throw new ArgumentException("passwordHash cannot be null, empty, or consist of whitespace."); 
      user.PasswordHash = passwordHash; 

     }); 
    } 

    public override async Task<ApplicationUser> FindByIdAsync(int userId) 
    { 
     var profile = await _db.ffs_profile.Where(u => u.profile_id == userId).FirstOrDefaultAsync(); 

     ApplicationUser user = null; 
     if (profile != null) 
      user = ToApplicationUser(profile); 

     return user; 
    } 

    public override Task<string> GetSecurityStampAsync(ApplicationUser user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException("user"); 
     } 
     return Task.FromResult<string>(user.SecurityStamp); 
    } 
    public override Task SetSecurityStampAsync(ApplicationUser user, string stamp) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException("user"); 
     } 
     user.SecurityStamp = stamp; 
     return Task.FromResult<int>(0); 
    } 
} 

그리고 마지막으로, 계정 컨트롤러의 관련 부분 :에

public class AccountController : Controller 
{ 
    private ApplicationSignInManager _signInManager; 
    private ApplicationUserManager _userManager; 

    public AccountController() 
    { 
    } 

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager) 
    { 
     UserManager = userManager; 
     SignInManager = signInManager; 
    } 

    public ApplicationUserManager UserManager 
    { 
     get 
     { 
      return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); 
     } 
     private set 
     { 
      _userManager = value; 
     } 
    } 
// other autogenerated methods 
[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = new ApplicationUser 
       { 
       //set props here 
      }; 
      try 
      { 
       IdentityResult result = await UserManager.CreateAsync(user, model.Password); 
       if (result.Succeeded) 
       { 

        await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); 


        return RedirectToAction("Index", "Home"); 
       } 
       AddErrors(result); 
      } 
      catch (Exception ex) 
      { 
       System.Diagnostics.Trace.WriteLine(ex.ToString()); 
      } 

     } 
     return View(model); 
    } 
} 

답변

0

많은 내 억울함, 나는 가지고 있었다. 위의 옵션 2를 사용하십시오. 연결 문자열을 일반 연결 문자열 (위 참조)처럼 변경 한 다음 결과적으로 이전에 처리하지 않은 UserManager 메서드 (예 : manager.GetRolesAsync() 및)를 재정의해야했습니다. 이제 비밀번호를 등록하고 재설정 할 수 있습니다.

관련 문제