2013年6月29日 星期六

設定User與Roles的第一筆種子(seed)資料, 客製化User的屬性 (在MVC4上使用SimpleRoleProvider, Entity Framework 5 CodeFirst)

只有網際網路應用程式(Internet Application)SimpleRoleProvider, 所以用這份版建立一個專案

即使是隱含存在的, 但是還是顯式的將providers加到<System.Web>裡面, 這樣當我們為了要migrations在套件管理器主控台(Package Manager Console)上執行update-database命令時, 我們可以使用本機的"Roles"API
    <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
      <providers>
        <clear/>
        <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
      </providers>
    </roleManager>
    <membership defaultProvider="SimpleMembershipProvider">
      <providers>
        <clear/>
        <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>

現在來客製化 User資料表, 加入Mobile 欄位到UserProfile 實體類別

    [Table("UserProfile")]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { getset; }
        public string UserName { getset; }
        [Display(Name = "電話")]
        public string Mobile { getset; }
    }

套件管理器主控台(Package Manager Console)啟用EF5 CodeFirst Migrations
PM> enable-Migrations
執行完後跑出Migrations資料夾

Migrations/Configuration.cs修改部分資料, 可執行種入我預備想要的Roles和任何User

    internal sealed class Configuration : DbMigrationsConfiguration<MvcApplication4.Models.UsersContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }
 
        protected override void Seed(MvcApplication4.Models.UsersContext context)
        {
            WebSecurity.InitializeDatabaseConnection(
                "DefaultConnection",
                "UserProfile",
                "UserId",
                "UserName", autoCreateTables: true);
            if (!Roles.RoleExists("Administrator"))
                Roles.CreateRole("Administrator");
 
            if (!WebSecurity.UserExists("ian100"))
                WebSecurity.CreateUserAndAccount(
                    "ian100""pw0000",
                    new { Mobile = "07888999" });
 
            if (!Roles.GetRolesForUser("ian100").Contains("Administrator"))
                Roles.AddUsersToRoles(new[] { "ian100" }, new[] { "Administrator" });
        }
    }


注意到WebSecurity.InitializeDatabaseConnection()發法被引用, 這方法是告訴SimpleMembership 哪個資料表我們要使用於Users, 哪個欄位是用於UserId UserName, 接著要在註冊頁面加入新增的客製化欄位

套件管理器主控台(Package Manager Console)執行
PM> update-database –verbose
(使用-verbose 可以在Package Manager Console看到生成的SQL)
執行最後可以看到正在執行 Seed 方法。
(如果沒有在Web.Confing加入providers設定, 則會在套件管理器主控台顯示錯誤 : 尚未啟用角色管理員功能。
此時Users 被新增, Roles被提供

Ian100被加入到且關聯到Administrator角色

現在執行最後一件事, 修改註冊相關頁面與類別(加入新增的欄位Mobile)
Register View (Register.cshtml)
// … 省略
<li>
    @Html.LabelFor(m => m.Mobile)
    @Html.TextBoxFor(m => m.Mobile)
</li>

Register model (AccountModel.cs)
public class RegisterModel
{
    // … 省略
    [Required]
    [DataType(DataType.PhoneNumber)]
    [Display(Name = "Mobile")]
    public string Mobile { get; set; }
}

Register Action (AccountController.cs)
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        // Attempt to register the user
        try
        {
            WebSecurity.CreateUserAndAccount(
                model.UserName,
                model.Password,
                new { Mobile = model.Mobile },
                false);

            WebSecurity.Login(model.UserName, model.Password);
            return RedirectToAction("Index", "Home");
        }
        catch (MembershipCreateUserException e)
        {
            ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
        }
    }

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

}

沒有留言: