喜帳面の日記

50歳越えおやじのASP.NET MVC への挑戦日記です。

Visual Studio Express 2012 for Web でいってみる 4.ログイン認証あたり2

 

前回に引き続き、Visual Studio Express 2012 for WebでMVC4の「Internet Application」テンプレートで新しいプロジェクトを作成すると、ログインやらユーザー登録機能がデフォルトで作成されますが、そのあたりについてのメモです。

 初心者が行き当たりばったりにいろいろ動かしてみたときのメモなので記載内容には勝手な解釈や誤りもあるかと思います。そのあたりのご指摘よろしくお願いします。

前回は『ユーザー名やパスワードはいったいどこに格納されるんだろう?』でしたが、今回の疑問は『ユーザー登録画面に項目を追加するにはどうする?』です。自動作成されるユーザー登録画面に例えば「メールアドレス」とかを追加する方法についてのレポートです。

結果から言うと、思ってたより簡単にできますです。


自動作成されたソースをデバッグで追っかけたところ、[WebSecurity.CreateUserAndAccount]でユーザー情報が登録されていることを確認。

以下の情報を参考にしました。

[msdn] WebSecurity Class

 
 [msdn] WebSecurity.CreateUserAndAccount Method

http://msdn.microsoft.com/en-us/library/webmatrix.webdata.websecurity.createuserandaccount(v=vs.99).aspx

※3つめのパラメータは

propertyValuesType: System.Object

(Optional) A dictionary that contains additional user attributes. The default is null.

ユーザー追加の属性を[dictionary]で指定となってます。ということは、ユーザーは属性を追加することができそうですね。

そこでで頑張って検索、以下の記事をみつけ、参考にさせてもらいました。

[三日坊主と呼ばせない!日記]

[ASP.NET][Razor]ASP.NET Web Pagesのメンバシップで追加のユーザ情報を扱う
WebMatrixでの説明ですが、この情報でばっちりです。感謝、感謝。

 1.テーブル[UserProfile]にカラム[Email]を追加

この作業は、SQLServer Managemant StudioやVisual Studio Express 2012 for Webのデータベースエクスプローラーで行います。

以下はVisual Studio Express 2012 for Webのデータベースエクスプローラーの例

f:id:SannomiyaNotes:20120907105422p:plain

 

2.モデルの変更

[Models]-[AccountModels.cs]に2点追加

①CreateUserAndAccount Methodの3つ目のパラメータ用のクラスを追加

public class UserProfileAddattributeModel
{
    public string Email { get; set; }
}

※このclassの追加は[AccountModels.cs]である必要はありません。別ファイルに分けてもよいのですが皆さんこんなケースではどうされてるんでしょう?

②ユーザー登録ページ用のモデル[RegisterModel]に今回追加した項目[Email]の定義を追加

public class RegisterModel
{
    [Required]
    [Display(Name = "ユーザー名")]
    public string UserName { get; set; }
...<省略>...
 [Required]
 [DataType(DataType.EmailAddress)] //この行はvalidationには無関係です。
 [RegularExpression(@"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$",ErrorMessage="Email形で入力してください。")]
 [Display(Name = "メールアドレス")]
 public string Email { get; set; }

 ※[DataType(DataType.EmailAddress)]ってのを、おまじないのように記述したのですが、何のご利益があるのかは現時点では不明です。今回の場合、「入力値の検証」には影響を及ぼしません。有効なメール型のチェックは次の行[RegularExpression...]の部分で行ってます。

 

3.コントローラーの変更

[Controllers]-[AccountController.cs]の

 public ActionResult Register(RegisterModel model) 

//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
  if (ModelState.IsValid)
  {
   // ユーザーの登録を試みます
    try
      {
         var UserProfileAddattributes = new UserProfileAddattributeModel(); // 1
         UserProfileAddattributes.Email = model.Email; // 2     
        //WebSecurity.CreateUserAndAccount(model.UserName, model.Password); // 3
         WebSecurity.CreateUserAndAccount(model.UserName, model.Password
         ,UserProfileAddattributes); // 4
                    
        WebSecurity.Login(model.UserName, model.Password);
        return RedirectToAction("Index", "Home");
      }
    catch (MembershipCreateUserException e)
      {
        ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
      }
   }
   // ここで問題が発生した場合はフォームを再表示します
    return View(model);
}

色付きの行の3行目に「WebSecurity.CreateUserAndAccount」があります。自動生成された行をコメントアウトし、3つ目のパラメータ(例では[UserProfileAddattributes])をセットするようにしています。

その[UserProfileAddattributes]にはその前の2行で、ユーザー登録ページで入力された値がセットされるようにしています。

※こんな場所でこんな風にやっていいのか? 自信ありません。ご指摘ください。

4.ビューの変更

[Views]-[Account]-[Register.cshtml]の

@model Mvc4Application6.Models.RegisterModel
@{
    ViewBag.Title = "ユーザーアカウントの登録";
}
<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
    <h2>新しいアカウントを作成します。</h2>
</hgroup>
@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()
    <fieldset>
        <legend>登録フォーム</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.UserName)
                @Html.TextBoxFor(m => m.UserName)
            </li>
            <li>
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)
            </li>
      <li>
      @Html.LabelFor(m => m.Email)
      @Html.TextBoxFor(m => m.Email)
      </li>
        </ol>
        <input type="submit" value="登録" />
    </fieldset>
}
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

 色付きの4行が追加した行です。

以上で、ソースの変更は終了です。

実行するとこんな感じ

f:id:SannomiyaNotes:20120909065156p:plain

Emailに[RegularExpression]で書式を付けおくと、こんなふうに書式を満たしていない状態のあいだ『赤い枠』が表示されます。


今回は、テーブル[UserProfile]にユーザー独自列[Email]を追加してみました。

列[Email]がテーブル[UserProfile]に存在するのが本当に妥当かって疑問もありますがそれはそれとして、[UserProfile]にユーザー独自列を追加する事例としてみてください。

あと、[Email]って項目についての疑問も残ってます。

[Email]って項目はそもそも.NET標準で用意されているんじゃないか?※注1

[UserName]にはEmailアドレスを入力するのが標準?

Roleってどうすれば使えるの?などなど

このあたり「WebSecurity Object」などについての勉強が必要なのかなあ。。と思うのですが、改めて何かわかったらアップしますね。


※注1:AccountController.csのユーザー登録処理でのエラーメッセージを返す処理[ErrorCodeToString]という関数には以下の記述があります。

// ソース開始
private static string ErrorCodeToString(MembershipCreateStatus createStatus)
{
    // すべてのステータス コードの一覧については、http://go.microsoft.com/fwlink/?LinkID=177550 を
    // 参照してください。
    switch (createStatus)
    {
        case MembershipCreateStatus.DuplicateUserName:
            return "このユーザー名は既に存在します。別のユーザー名を入力してください。";
        case MembershipCreateStatus.DuplicateEmail:
 return "その電子メール アドレスのユーザー名は既に存在します。別の電子メール アドレスを入力してください。";
        case MembershipCreateStatus.InvalidPassword:
            return "指定されたパスワードは無効です。有効なパスワードの値を入力してください。";
        case MembershipCreateStatus.InvalidEmail:
 return "指定された電子メール アドレスは無効です。値を確認してやり直してください。";

<以下省略>

 


今回は以上です。

初心者が行き当たりばったりにいろいろ動かしてみたときのメモなので記載内容には勝手な解釈や誤りもあるかと思います。そのあたりのご指摘よろしくお願いします。