Asp.net-Mvc

Microsoft.AspNet.Identity 的自定義成員身份 - CreateLocalUser 失敗

  • July 28, 2013

我一直在嘗試使用 Visual Studio 2013 在 ASP.NET 4.5 (Microsoft.AspNet.Identity) 中實現新身份功能的自定義版本。經過數小時的嘗試,我將程式碼簡化為努力讓它沒有錯誤地執行。我在下面列出了我的程式碼。進行本地註冊時,會創建數據庫表,但 CreateLocalUser 方法失敗。我希望有人可以幫助我確定所需的更改。

模型/會員模型.cs

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace thePulse.web.Models
{
   public class PulseUser : IUser
   {
       public PulseUser() { }
       public PulseUser(string userName) 
       {
           UserName = userName;
       }

       [Key]
       public string Id { get; set; }
       [Required]
       [StringLength(20)]
       public string UserName { get; set; }
       [StringLength(100)]
       public string Email { get; set; }
       [Column(TypeName = "Date")]
       public DateTime? BirthDate { get; set; }
       [StringLength(1)]
       public string Gender { get; set; }
   }

   public class PulseUserClaim : IUserClaim
   {
       public PulseUserClaim() { }

       [Key]
       public string Key { get; set; }
       public string UserId { get; set; }
       public string ClaimType { get; set; }
       public string ClaimValue { get; set; }

   }

   public class PulseUserSecret : IUserSecret
   {
       public PulseUserSecret() { }
       public PulseUserSecret(string userName, string secret)
       {
           UserName = userName;
           Secret = secret;
       }

       [Key]
       public string UserName { get; set; }
       public string Secret { get; set; }

   }

   public class PulseUserLogin : IUserLogin
   {
       public PulseUserLogin() { }
       public PulseUserLogin(string userId, string loginProvider, string providerKey) 
       {
           LoginProvider = LoginProvider;
           ProviderKey = providerKey;
           UserId = userId;
       }

       [Key, Column(Order = 0)]
       public string LoginProvider { get; set; }
       [Key, Column(Order = 1)]
       public string ProviderKey { get; set; }
       public string UserId { get; set; }
   }

   public class PulseRole : IRole
   {
       public PulseRole() { }
       public PulseRole(string roleId)
       {
           Id = roleId;
       }

       [Key]
       public string Id { get; set; }
   }

   public class PulseUserRole : IUserRole
   {
       public PulseUserRole() { }

       [Key, Column(Order = 0)]
       public string RoleId { get; set; }
       [Key, Column(Order = 1)]
       public string UserId { get; set; }
   }

   public class PulseUserContext : IdentityStoreContext
   {
       public PulseUserContext(DbContext db) : base(db)
       {
           Users = new UserStore<PulseUser>(db);
           Logins = new UserLoginStore<PulseUserLogin>(db);
           Roles = new RoleStore<PulseRole, PulseUserRole>(db);
           Secrets = new UserSecretStore<PulseUserSecret>(db);
           UserClaims = new UserClaimStore<PulseUserClaim>(db);
       }
   }

   public class PulseDbContext : IdentityDbContext<PulseUser, PulseUserClaim, PulseUserSecret, PulseUserLogin, PulseRole, PulseUserRole>
   {
   }
}

對控制器/AccountController.cs 的更改

public AccountController() 
{

   IdentityStore = new IdentityStoreManager(new PulseUserContext(new PulseDbContext()));
   AuthenticationManager = new IdentityAuthenticationManager(IdentityStore);
}

//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
   if (ModelState.IsValid)
   {
       try
       {
           // Create a profile, password, and link the local login before signing in the user
           PulseUser user = new PulseUser(model.UserName);
           if (await IdentityStore.CreateLocalUser(user, model.Password))
           {
               await AuthenticationManager.SignIn(HttpContext, user.Id, isPersistent: false);
               return RedirectToAction("Index", "Home");
           }
           else
           {
               ModelState.AddModelError("", "Failed to register user name: " + model.UserName);
           }
       }
       catch (IdentityException e)
       {
           ModelState.AddModelError("", e.Message);
       }
   }

   // If we got this far, something failed, redisplay form
   return View(model);
}

如上所述,當 CreateLocalUser 方法失敗 (Microsoft.AspNet.Identity.EntityFramework) 時,此實現將失敗。我不知道為什麼。

這裡的問題是 IdentityStoreManager 對身份 EF 模型的預設實現有很強的依賴性。例如,CreateLocalUser 方法將創建 UserSecret 和 UserLogin 對象並將它們保存到商店,如果商店不使用預設模型類型,則該方法將不起作用。因此,如果您自定義模型類型,它將無法與 IdentityStoreManager 順利配合使用。

由於您只自定義 IUser 模型,因此我簡化了程式碼以從預設身份使用者繼承自定義使用者並重用身份 EF 模型中的其他模型。

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace WebApplication11.Models
{
   public class PulseUser : User
   {
       public PulseUser() { }
       public PulseUser(string userName) : base(userName)
       {
       }

       [StringLength(100)]
       public string Email { get; set; }
       [Column(TypeName = "Date")]
       public DateTime? BirthDate { get; set; }
       [StringLength(1)]
       public string Gender { get; set; }
   }

   public class PulseUserContext : IdentityStoreContext
   {
       public PulseUserContext(DbContext db) : base(db)
       {
           this.Users = new UserStore<PulseUser>(this.DbContext);
       }
   }

   public class PulseDbContext : IdentityDbContext<PulseUser, UserClaim, UserSecret, UserLogin, Role, UserRole>
   {
   }
}

上面的程式碼應該適用於 Identity API 的預覽版。

即將發布的 IdentityStoreManager API 已經意識到了這個問題,並將所有非 EF 依賴程式碼更改為基類,以便您可以通過繼承來自定義它。它應該解決這裡的所有問題。謝謝。

引用自:https://stackoverflow.com/questions/17911430