2014年2月14日 星期五

AspNet Identity 玩弄手札 第一彈 Code First 自訂 profile data

One ASP.NET 表示:天下大勢,分久必合,合久必分

AspNet Identity 表示:我也不過是被 One ASP.NET 玩弄於股掌之間的一個犧牲者

老疆表示:程式設計師用一些點子來做一些無聊事情,這樣瞭不瞭

第一次聽到 AspNet Identity 是 老疆 的影片

http://www.youtube.com/watch?v=G2JC4KWTqXM&list=PLSvKFCIcFiosRfhmjcSCozircig3dRRrR&index=1

(11:15開始)

老疆的演講都很有梗

而且梗都是模仿不來的

別人說都不好笑 但是聽他講卻又有種獨特的幽默

我想這是一種 Aura









首先來玩 Micro$oft 最愛表演的戲碼 Code First + 自訂 profile data 神奇搞定會員登入功能

打開 VS 2013 建立一個 MVC 專案

他預設很好心的就準備好一堆範例程式 讓我們熟悉 他新攪和進來的東東

其實馬上就能執行了 可以註冊 登入 都沒問題



因為是 Code First 所以第一次呼叫 DbContext 的時候 會自動建立好 DB 跟 TABLE



以往要擴充 profile data 十分麻煩 有多麻煩我也不太瞭

因為相傳 業界公司 沒有人在用 都是自幹 會員機制 而我也不過是其中一人

現在他表明了 You can add profile data for the user by adding more properties to your ApplicationUser class

在這邊加屬性就搞定了

// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
    public string Email { getset; }
 
    public int Point { getset; }
 
    public bool Gender { getset; }
 
    public DateTime Birthday { getset; }
}

原先的 RegisterViewModel 也順手加上 以利欄位驗證

public class RegisterViewModel
{
    [Required]
    [Display(Name = "使用者名稱")]
    public string UserName { getset; }
 
    [Required]
    [StringLength(100,
        ErrorMessage = "{0} 的長度至少必須為 {2} 個字元。",
        MinimumLength = 6
    )]
    [DataType(DataType.Password)]
    [Display(Name = "密碼")]
    public string Password { getset; }
 
    [DataType(DataType.Password)]
    [Display(Name = "確認密碼")]
    [Compare("Password"ErrorMessage = "密碼和確認密碼不相符。")]
    public string ConfirmPassword { getset; }
 
    [Required]
    [EmailAddress]
    [Display(Name = "E - mail")]
    public string Email { getset; }
 
    [Required]
    [Display(Name = "點數")]
    public int Point { getset; }
 
    [Required]
    [Display(Name = "性別")]
    public bool Gender { getset; }
 
    [DataType(DataType.Date)]
    [Display(Name = "生日")]
    public DateTime Birthday { getset; }
}

AccountController 的 Register 也要從 ViewModel 把值帶入 ApplicationUser

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser()
        {
            UserName = model.UserName,
            Email = model.Email,
            Point = model.Point,
            Gender = model.Gender,
            Birthday = model.Birthday
        };
 
        var result = await UserManager.CreateAsync(usermodel.Password);
        if (result.Succeeded)
        {
            await SignInAsync(userisPersistentfalse);
            return RedirectToAction("Index""Home");
        }
        else
        {
            AddErrors(result);
        }
    }
 
    // 如果執行到這裡,發生某項失敗,則重新顯示表單
    return View(model);
}

如果你覺得欄位很多很給掰 可以使用一些 Mapping 或者 Injecter 的套件

像是 Value Injecte



只要屬性名稱一致 就能無腦的搞定

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser().InjectFrom(modelas ApplicationUser;
 
        var result = await UserManager.CreateAsync(usermodel.Password);
        if (result.Succeeded)
        {
            await SignInAsync(userisPersistentfalse);
            return RedirectToAction("Index""Home");
        }
        else
        {
            AddErrors(result);
        }
    }
 
    // 如果執行到這裡,發生某項失敗,則重新顯示表單
    return View(model);
}

最後當然別忘了 View 可不會自動生出 HTML 也補上

<div class="form-group">
    @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Point, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Point, new { @class = "form-control" })
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Gender, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        男
        @Html.RadioButtonFor(
            m => m.Gender, true, new { @id = "", @checked = "checked" })
        女
        @Html.RadioButtonFor(
            m => m.Gender, false, new { @id = "" })
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Birthday, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Birthday, new { @class = "form-control" })
    </div>
</div>



搞定 馬上開心執行 立馬報錯 -.-



因為先前執行過一次已經 產生過 DB 跟 TABLE

但是這次 Code First 發現 schema 被異動過 無法 ORM 就跳錯了

請透過 套件管理主控台 來更新他

我們可以在 檢視/其他視窗/套件管理主控台 找到這貨

啟用轉移:Enable-Migrations -ContextTypeName MvcSample.ApplicationDbContext

轉移版本:Add-Migration '版本名稱'

更新資料庫:Update-Database

出現 Seed 就表示成功啦



這下搞定了 資料乖乖進 DB 可喜可賀



沒有留言:

張貼留言