TempDataを使ってセッション情報を保持するプログラム
今回は、ログイン後にIDとユーザー名を画面の上部に表示するプログラムを作成します。
表示するユーザー情報は、ログアウトするまで有効になるようにします。
画面イメージは、以下のようになります。
なお、エラー処理は、処理が煩雑になるので実装していません。
ログイン前の画面
ログイン後の画面
画面の右上に、ID、ユーザー名、ログアウトのリンクが表示されます。
新規プロジェクトの作成
新規にプロジェクトを作成します。
今回のサンプルプログラムでは、プロジェクト名を「Test8」として作成します。
プロジェクトの作成方法は、こちらの記事を参照してください。
データベースの作成
プロジェクトで使用するデータベースを作成します。
データベースは、Visual Studio付属の「SQL Server Express LocalDB」を使用します。
データベースの仕様や作成方法は、こちらの記事を参照してください。
ADO.NET Entity Data Modelの作成
データベースを作成したら、VB.NETとデータベースを接続するために、ADO.NET Entity Data Modelを作成します。
モデル名は、「TestDbModel」とします。
ADO.NET Entity Data Modelの作成方法は、こちらの記事を参照してください。
Accountクラスにアノテーションを追加
自動で作成されたAccountクラスの各プロパティに、アノテーションを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Imports System Imports System.Collections.Generic Imports System.ComponentModel Imports System.ComponentModel.DataAnnotations Partial Public Class Account <DisplayName("ID")> Public Property Id As Integer <DisplayName("氏名")> Public Property Name As String <DisplayName("パスワード")> Public Property Password As String End Class |
データベース操作用クラスの作成
データベースを操作するためのクラスを、「DbModel.vb」という名前で、「Data」フォルダーの配下に作成します。
「Data」フォルダーは、あらかじめ作成しておきます。
このクラスでは、ログイン画面で入力されたIDとパスワードを使って、ユーザー情報を取得する関数を作成します。
検索結果は0件か1件になるので、SQLQuery()メソッドにFirstOrDefault()メソッドを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Public Class DbModel Function GetAccount(id As Integer, password As String) As Account Dim account As Account Dim sql As String = $" SELECT Id, Name, Password FROM Account WHERE Id={id} and Password='{password}'; " Using db As New TestDbEntities account = db.Database.SqlQuery(Of Account)(sql).FirstOrDefault() End Using Return account End Function End Class |
今回はサンプルなので、テーブルから取得したデータを格納するモデルを自動で作成されたAccountクラスにしていますが、パスワードは不要なので、本来はIdとNameのみのプロパティを持ったクラスを新規に作成した方が良いです。
ログイン画面用コントローラーの作成
ログイン画面用のコントローラーを作成します。
データベースから取得したユーザー情報をTempData("Value")に格納して、以降、このデータをログアウトするまで、TempData("Value")に保持したまま使い回します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Imports System.Web.Mvc Namespace Controllers Public Class LoginController Inherits Controller <HttpGet()> Function Login() As ActionResult Return View() End Function <HttpPost()> Function Login(vm As Account) As ActionResult Dim model As New DbModel Dim data As Account = model.GetAccount(vm.Id, vm.Password) TempData("Value") = data Return RedirectToAction("MyPage", "Home") End Function End Class End Namespace |
ログイン画面用ビューの作成
ログイン画面用のビューを作成します。
このビューでは、IDとパスワードを入力させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@ModelType Account @Code ViewData("Title") = "Login" End Code <div class="login"> <div class="label"> <p>@Html.LabelFor(Function(model) model.Id):</p> <p>@Html.LabelFor(Function(model) model.Password):</p> </div> <div class="input-box"> @Using Html.BeginForm("Login", "Login", FormMethod.Post) @<p> @Html.TextBoxFor(Function(model) model.Id, New With {.maxlength = "20"}) </p> @<p> @Html.PasswordFor(Function(model) model.Password, New With {.maxlength = "20"}) </p> @<input type="submit" value="ログイン" /> End Using </div> </div> |
表示レイアウトの編集
ビューを作成すると、自動的に「Views/Shared/_Layout.vbhtml」が作成されるので、これを以下のように編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Code Dim account As Account = TempData.Peek("Value") End Code <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <title>@ViewBag.Title - My ASP.NET Application</title> <link href="~/Content/Site.css" rel="stylesheet" type="text/css" /> </head> <body> @If account Is Nothing Then @<div class="account">未ログイン</div> Else Dim user As String = $"{account.Id}:{account.Name}" @<div class="account">@user<span class="logout"><a href="/Logout/Logout">ログアウト</a></span></div> End If @RenderBody() </body> </html> |
12行目から17行目で画面の上部に表示するユーザー情報を設定します。
ログインする前は、「未ログイン」と表示します。
2行目でTempData("Value")から値を取得する時に、Peek()メソッドを使ってTempData("Value")の値を保持し続けます。
Peek()メソッドを使用しない場合は、ここでTempData(”Value”)の値が破棄されてしまいます。
TempData()に関する詳しい内容は、以下のマイクロソフトの公式サイトを参照してください。
ログイン完了画面用コントローラーの作成
ログイン完了画面用のコントローラーを作成します。
1 2 3 4 5 6 7 8 9 10 11 |
Imports System.Web.Mvc Namespace Controllers Public Class HomeController Inherits Controller Function MyPage() As ActionResult Return View() End Function End Class End Namespace |
ログイン完了画面用ビューの作成
ログイン完了画面用のビューを作成します。
7、8行目でTempData("Value")から値を取得していますが、ここでもPeek()メソッドを使用します。
Peek()メソッドを使用しないと、TempData("Value")の内容が破棄されてしまいます。
1 2 3 4 5 6 7 8 9 |
@ModelType Account @Code ViewData("Title") = "MyPage" End Code <h2>ログイン完了</h2> <p>@Html.LabelFor(Function(model) model.Id):@TempData.Peek("Value").Id</p> <p>@Html.LabelFor(Function(model) model.Name):@TempData.Peek("Value").Name</p> <a href="/Detail/Detail">詳細画面</a> |
詳細画面用コントローラーの作成
詳細画面用のコントローラーを作成します。
1 2 3 4 5 6 7 8 9 10 11 |
Imports System.Web.Mvc Namespace Controllers Public Class DetailController Inherits Controller Function Detail() As ActionResult Return View() End Function End Class End Namespace |
詳細画面用のビューを作成
詳細画面用のビューを作成します。
詳細画面は、単にログイン完了画面から遷移するために使いたいだけなので、内容は特にありません。
1 2 3 4 5 6 |
@Code ViewData("Title") = "Detail" End Code <h2>詳細画面</h2> <a href="/Home/MyPage">戻る</a> |
ログアウト用コントローラーの作成
ログアウト用のコントローラーを作成します。
このコントローラー内で、TempData()の値をクリアします。
今回は、TempData("Value")しか使っていませんが、TempData().Clearとすると、全てのTempData()の項目が削除されます。
また、ログアウト用のビューは作成せず、ログイン画面に戻ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Imports System.Web.Mvc Namespace Controllers Public Class LogoutController Inherits Controller Function Logout() As ActionResult '全てのTempDataをクリア TempData().Clear() Return RedirectToAction("Login", "Login") End Function End Class End Namespace |
スタイルシートの修正
このプロジェクトで使用するスタイルシート(Site.css)を、以下のように修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
body { margin: 10px; padding: 10px; } .login { height: 200px; width: 700px; margin: 50px auto 0; overflow: hidden; } .label { width: 30%; text-align: right; float: left; } .input-box { width: 70%; float: left; } .account { height: 20px; width: 300px; margin: 5px 0 0 80%; } .logout { padding-right: 10px; float: right; } |
32行目は、ログアウトのリンクを右端に寄せるための指定です。
floatを使うことで、インライン要素をブロック要素にして位置を指定することが出来るようになります。
RouteConfigの修正
RouteConfig.vbを修正して、ルートページをログイン画面になるように変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Web Imports System.Web.Mvc Imports System.Web.Routing Public Module RouteConfig Public Sub RegisterRoutes(ByVal routes As RouteCollection) routes.IgnoreRoute("{resource}.axd/{*pathInfo}") routes.MapRoute( name:="Default", url:="{controller}/{action}/{id}", defaults:=New With {.controller = "Login", .action = "Login", .id = UrlParameter.Optional} ) End Sub End Module |