2017-02-03 41 views
1

因此,我在現有數據庫上構建了一個應用程序,我有限制的權限可以更改(想法是儘可能少地更改數據庫模式)。這是一個MVC 5應用程序,試圖將自定義用戶存儲的身份系統用於MySQL數據庫。實體類型ApplicationUser不是當前上下文的模型的一部分,DB首先使用自定義用戶存儲

問題:我發現了試圖在寄存器方法來註冊通過自動生成的AccountController用戶當以下情況例外:

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

System.InvalidOperationException:的實體類型ApplicationUser是不是當前情況下的模型的一部分。 在System.Data.Entity.Internal.InternalContext.UpdateEntitySetMappingsForType(類型的EntityType) 在System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(類型的EntityType) 在System.Data.Entity.Internal.Linq.InternalSet 1.Initialize() at System.Data.Entity.Internal.Linq.InternalSet 1。 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" /> 。這個意外爆炸很快就會發生無意識代碼的第一個異常還有其他一些問題似乎在螺旋上升(在解決了桌子上沒有聲明的Keys等問題之後),我對這方面的建議持開放態度,但寧願不必走這條路。

下面是與設置相關的代碼。任何想法還有什麼我可以在這裏失蹤?或者是連接字符串想法解決這個問題的唯一方法?

謝謝!

設置 我使用數據庫優先(EDMX)到現有的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()manager.CreateIdentityAsync)。我現在可以註冊,重置密碼等。

相關問題