Upload
jz5-matsue
View
917
Download
8
Embed Size (px)
Citation preview
はじめての ASP.NET MVC
2015/4/11ASP.NET 初心者勉強会@jz5(プロ生)
自己紹介• @jz5• プロ生ちゃんP• ASP.NET 初心者• 運営
– プログラミング生放送– IT 勉強会スタンプラリー
今回の内容• 扱うこと
– ASP.NET MVC で Web サイトを作る– ○○すれば□□ができるみたいな
• 扱わないこと– MVC とはみたいな– ○○すればどういう仕組みで□□が実現できているみたいな
対象• 環境
– Visual Studio 2013/2015 CTP 5• 対象者
– ASP.NET MVC でサイトを作ったことないひと– プログラミングある程度できるひと
注意• 実際にサイトを作って理解したことを書いています。細
かな定義や意味合いは異なるかも。• 次期 ASP.NET MVC はどうなるか知りません
ASP.NET MVC で作ったサイト紹介• IT 勉強会スタンプ• パスワードを平文で送ってくるっぽいサイトまとめ• リツイート直後のツイートを表示するやつ• timg: Twitter 画像検索・画像一覧• その他 画像ジェネレーター系や
プレゼント応募フォームなど
IT勉強会スタンプ• Git リポジトリ
– https://github.com/jz5/it-stamp• 関連技術
– SQL Server– Azure Web アプリ
• ASP.NET 機能– ユーザー認証– Facebook/Twitter/Google サインイン– Role 機能– メール機能– (ツイート機能)※ ASP.NET の仕組みとは直接関係なし
プロジェクトの作成
プロジェクト新規作成1. Visual Basic/C# → Web
→ ASP.NET Webアプリケーションプロジェクト2. 「MVC」選択3. 「認証の変更」
– 「認証なし」– 「個人ユーザー アカウント」: SQL Server を使ったユーザー情
報を保存する仕組みが使える。Twitter/Facebook/Google などのサインイン機能も使える。
※ SNS サインイン機能だけ使って情報を保存しない場合は「認証なし」から始めた方が良いかも
プロジェクトを作成したら• NuGet パッケージの管理からプログラムを更新しておく
ちなみにプロジェクトサイズは80MBぐらい
プロジェクトの構成
• ルーティング• コントローラー• ビュー
ルーティング• App_Start/RouteConfig.cs で URL の構成を決めるroutes.MapRoute(
name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional });
デフォルト
http://localhost/Account/Login?returnUrl=/Home{コントローラー名} {アクション名} {オプションのパラメーター}
→ アクセスすると AccountController クラスのLogin メソッドを実行
ルーティング• http://localhost/Event/1 のようにアクセスしたいroutes.MapRoute(
name:"Events",url:"Events/{id}",defaults:new {controller = "Events", action = "Details"},constraints: new {id = "¥¥d+"}
);
Events/{id} のアクセスはコントローラーとアクションを固定
追記
コントローラー• HTTP リクエストを処理して表示するビューを決める• Controllers フォルダーにある
– AccountController.cs– HomeController.cs– ManageController.cs※ 「個人ユーザー アカウント」で作成した場合
コントローラー• AccountController.cs[AllowAnonymous]public ActionResult Login(string returnUrl){
ViewBag.ReturnUrl = returnUrl;return View();
}
Account/Login に GET アクセスしたときに実行されるAccount/Login?returnUrl=/Home のようなアクセスは引数 returnUrl に /Home が入っている
コントローラー• AccountController.cs[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public async Task<ActionResult> Login(LoginViewModel model, string returnUrl){
...}
Account/Login に POST アクセスしたときはこっちが実行される[HttpPost] 属性で POST アクセスを指定
コントローラー• ビューを返すpublic ActionResult Login(string returnUrl){
ViewBag.ReturnUrl = returnUrl;return View();
}
return View("Error");
return RedirectToAction("Index", "Home");
→ Account/Login ビューを表示
→ Account/Error ビューを表示
→ Home/Index にリダイレクト
ビュー• 表示する ページ(HTML + α)• コントローラーからデータを受け取る
(コントローラでビューにデータを指定していた場合)• Views フォルダーにある
– Account/Login.cshtml など• コントローラーで Account/Login ビューを返すと
このファイルの内容が表示/実行される• Razor 記法で記述
– HTML の中にロジックなどを埋め込める
Razor 記法• 「ASP.NET Razor」で検索• ポイント的なところ
– @model LoginViewModel• コントローラーから受け取った LoginViewModel クラスのオブジェクト
– 親レイアウトなどテンプレート化できる(されている)• Shared/_Layout.cshtml(@RenderBody() に子のビューを表示)
– Html ヘルパーで HTML を短く書ける
<input class="form-control" data-val="true" data-val-email="電子メールフィールドは有効な電子メールアドレスではありません。" data-val-required="電子メールフィールドが必要です。" id="Email" name="Email" type="text" value="" />
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
→
ここまでのまとめ• ルーティングで指定したコントローラーのアクション(メソッ
ド)が実行される• コントローラーは要求を処理して表示するビューを決める
– 要求をもとにデータベースにアクセスしてなんやらしたりする• ビューはコントローラーのデータを受け取って Web ページを表
示する
モデルを操作する
• モデルと Code First• モデルを作成• Code First で DB のテーブル作成• モデルを操作する
コントローラーとビューの作成
モデル• Web アプリで扱うデータ(DB に格納するデータ)
– ユーザー情報など
Code First• DB のテーブルをコードから作る方法
– 特別な専用のコードではなく通常のクラスを記述する– 記述したクラスはアプリでそのまま使える
モデル作成• 例:イベント情報• Models/Events.cs
public class Event{
[Key]public int Id { get; set; }
[Required]public string Name { get; set; }
public DateTime StartDateTime { get; set; }}
モデル作成• DB に格納するモデルは ApplicationDbContext クラ
スで操作する• Models/IdentityModels.cs の
ApplicationDbContext クラスに追記public DbSet<Event> Events { get; set; }
DB のテーブル作成1. プロジェクトのビルド2. パッケージマネージャー コンソール表示
– [ツール]-[NuGet パッケージマネージャー] から3. Enable-Migrations コマンド実行
– メッセージ「Code First Migrations がプロジェクト○○で有効になりました。」
– Migrations/Configuration.cs ができている
DB のテーブル作成4. Configuration.cs
– AutomaticMigrationsEnabled = true; に修正5. Update-Database コマンド実行
– DB の構成変更完了
Configuration.csとUpdate-Database• Configuration クラスの Seed メソッド
– Update-Database 実行時に処理する内容を記述できる• 初期ユーザーの生成など
• Update-Database– モデルを修正するたびに実行– DB のデータ内容を維持してテーブル構造をモデルに合わせる– データ内容を維持できない場合は –force パラメーターを付けて実
行(必要なときは実行時にメッセージが表示される)– App_Data フォルダーにある .mdf ファイルを削除して作り直すの
もアリ
コントローラーとビューの作成1. ソリューションエクスプローラー Contollers コンテキストメ
ニュー [追加]-[コントローラー]2. 「Entity Framework を使用した、ビューがある MVC 5 コン
トローラー」を「追加」3. データコンテキスト クラスで「ApplicationDbContext」選択4. モデル クラスで「Event」選択して「追加」
→ Contollers/EventContoller.cs と Views/Events が生成Event の一覧・表示・作成・編集・削除が可能なコードが生成されているので,これを元にアプリに必要な処理を実装していく
Events/Index 一覧表示• コントローラー: DB の内容をビューに渡すpublic ActionResult Index(){
return View(db.Events.ToList());} ※ db: new ApplicationDbContext
• ビュー– @model IEnumerable<Models.Event> 扱うモデルの型を指定– @foreach (var item in Model) { ... } 一覧表示
• 「Model」で参照できる
Events/Create 作成(ビュー側)• ビュー
– @model Models.Event:扱うモデルの型– フォームの作成@using (Html.BeginForm()) {
[email protected](model => model.Name, ...)@Html.ValidationMessageFor(model => model.Name, "“, ...)...
}
Events/Create 作成(コントローラー側)
• コントローラー[HttpPost][ValidateAntiForgeryToken]public ActionResult Create(Event @event){
if (ModelState.IsValid){
db.Events.Add(@event);db.SaveChanges();return RedirectToAction("Index");
}return View(@event);
}
<input id="Name" name="Name" type="text" value="勉強会" />
input の値がプロパティに設定されたevent オブジェクトとして受け取れる
モデルバインディング
モデルバインディング• 「ASP.NET モデルバインディング」で検索• Events/Createでは ビュー側の @model とコントロー
ラー側のメソッドの引数 events の型が一致していたが,一致している必要はない– リクエストデータは,一致する引数名やクラスのプロパティ名
の値に設定される
ユーザー認証(サインイン機能)
ASP.NET Identity
ASP.NET Identity• 「ASP.NET Identity」で検索• ASP.NET の認証や資格管理のシステム• いろいろな仕組みを提供してカスタマイズや独自実装が可能
ユーザー認証の機能(1/2)• ユーザー認証の仕組みが実装されている
– デフォルトはメールアドレスを一意なユーザー名として使用– DB にユーザー情報を格納(AspNet から始まるテーブル名)
ユーザー認証の機能(2/2)• 枠組みだけ用意されている機能
– メールによるパスワードリセットなど• メールを送信する部分は要実装
– 2段階認証(使ったことないけど)• SMS 部分は要実装
– Facebook/Twitter/Google アカウントによるログイン• 各サービスの ID/Secret key を指定すれば使える
– Role の実装(管理者ユーザー権限などを付けたい場合)• 生成されるコードにサンプルコードは記述されていない
– ApplicationRoleManager, RoleManager などで検索– IT 勉強会スタンプは実装している
枠組みだけ用意されている機能の実装• App_Start/IdentityConfig.cs の編集
– EmailService クラスの実装など• App_Start/Startup.Auth.cs の編集
– Facebook/Twitter/Google ID, Secret key 指定など
ユーザー情報のカスタマイズ• ApplicationUser クラス(IdentifyModels.cs)に
プロパティを追加して Update-Database 実行– AspNetUsers テーブルに追加される
ユーザー認証のカスタマイズ• ユーザー名の設定やメールアドレスまたはユーザー名で
サインイン可能にするなど• AccountContoller などの編集(自分で実装)
– ユーザーの登録処理などは AccountContoller に記述されている。デフォルトのユーザー認証の機能を確認して、少しずつ修正していくといいと思う。
Azure Web アプリで公開
Azure Web アプリ(旧 Azure Websites )
• 「Azure Web アプリ」で検索• 使うポイント
– Visual Studio から簡単に Web アプリとして公開可能• データベースの新規作成,Code First 実行(DB 構造の変更)なども
可能– Visual Studio でリモートデバッグ可能
発行• ソリューションエクスプローラーのプロジェクト コンテキストメ
ニュー[発行]• 「Microsoft Azure Websites」から「新規」を選択
いろいろなトピック
細かなことはサイト参照や検索してください
複雑なモデル• プロパティがクラス(プリミティブ型でない)
– virtual 修飾子が必要• 多対多の関係
– マッピングの記述が必要• 参考「コード・ファースト開発の基本」
– http://blog.shibayan.jp/entry/20101014/1287061553
.mdf を削除したら再度作れなくなった• LocalDb インスタンスを終了させるコマンド
– sqllocaldb stop v11.0– sqllocaldb delete v11.0
• http://adamstephensen.com/2014/03/06/entity-framework-code-first-delete-a-localdb-instance/
HTTPS にする1. プロジェクトのプロパティウィンドウ「開発サーバー」
1. 「SSL 有効」を True2. 「SSL URL」をコピー
2. プロジェクトのプロパティ「Web」の「プロジェクトのURL」にペースト
3. コントローラー クラスまたはそのメソッドに[RequireHttps] 属性を付け HTTPS のみ許可する
CSRF 対策• 生成されるコードは既にされている• ビュー側
– form 内に @Html.AntiForgeryToken() 記述• コントローラー側
– メソッドに [ValidateAntiForgeryToken] 属性
アクセス許可設定• コントローラーのクラスやメソッドに属性を指定
– 誰でもアクセスできる• [AllowAnonymous]
– サインインしたユーザーのみアクセスできる• [Authorize]
– 「Admin」Role ユーザーのみアクセスできる• [Authorize(Roles="Admin")]
Ajax で POST 処理• NuGet パッケージ
「Microsoft.jQuery.Unobtrusive.Ajax」追加• ビュー
– Html.BeginForm → Ajax.BeginForm に変更(パラメーターも要修正)
– JavaScript でデータ受け取り,表示反映などの処理が必要• コントローラー
– ビューではなくJSON データを返すよう修正
JSON データを返す
• return Json(object_data);– 匿名クラスでも通常のクラスのオブジェクトでも JSON に変
換して返す• Ajax によるアクセスか判定は Request.IsAjaxRequest()
ツイート機能をつけたい• ID/Secret key 指定のみではサインインできるだけ• ツイートする仕組みなどを実装するにはサインイン時に
アクセストークンなども受け取るようTwitterAuthenticationProvider の指定が必要(次スライド)– 追加情報は DB に保存される(AspNetUserClaim テーブル)
TwitterAuthenticationProvider の指定app.UseTwitterAuthentication(
new TwitterAuthenticationOptions(){
ConsumerKey = "**TwitterConsumerKey**",ConsumerSecret = "**TwitterConsumerSecret**",Provider = new TwitterAuthenticationProvider(){
OnAuthenticated = async (context) =>{
context.Identity.AddClaim(new Claim("urn:tokens:twitter:accesstoken", context.AccessToken));
context.Identity.AddClaim(new Claim("urn:tokens:twitter:accesstokensecret", context.AccessTokenSecret));
}}
});参考: http://blogs.msdn.com/b/tsmatsuz/archive/2014/06/16/asp-net-identity-get-claim-scope-and-access-token-using-external-login-of-google-facebook-twitter-microsoft-account.aspx
Claim 情報の取得var accsessTokenClaim = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>().GetClaims("userId").FirstOrDefault((x) => x.Type == "urn:tokens:twitter:accesstoken");
Twitter ライブラリー• CoreTweet などの NuGet パッケージを追加して
ツイート処理を実装
DB なしで Twitter サインイン機能だけ実装
• 「認証なし」のプロジェクトを作成• 必要な NuGet パッケージを追加
– Microsoft.Owin– Microsoft.Owin.Host.SystemWeb– Microsoft.Owin.Security– Microsoft.Owin.Security.Cookies– Microsoft.Owin.Security.Twitter– Owin
• Startup.Auth.cs, Startup.cs, Controller の実装• 参考「Using Owin External Login without ASP.NET Identity」
– http://coding.abel.nu/2014/11/using-owin-external-login-without-asp-net-identity/– Global.aspx Application_Start() に AntiForgeryConfig.UniqueClaimTypeIdentifier =
ClaimTypes.Name; 追記
Azure Web アプリ関連いろいろトピック
日時と言語• UTC• en-US• web.config で変更不可
ログの取得• アクセスログはデフォルトで保存されていない• 旧 Portal の Web アプリの「構成」の「サイト診断」の
「Web サーバーのログ記録」で有効化できる
実際にあったこと: 現象と原因• 現象
• 旧 Azure Portal のダッシュボードで見ると大量の HTTP サーバーエラーが発生
– 原因(アクセスログを確認して判明)• コントローラーに引数が必要なアクションを用意していた(パラメー
ターが必要な URL)– 引数なしの場合は HTTP エラーを返していた
• Google のクローラーがパラメーターなしの URL にアクセスしていた
リモートデバッグ• 「Visual Studio で Azure のプロジェクトを Remote
Debug する」• http://blogs.msdn.com/b/tsmatsuz/archive/2013/01/31/windo
ws-azure-remote-debug-using-visual-studio-2012.aspx
オマケ: アプリを完成させるには
細かいことを気にしない• とりあえず動くものを公開する• 気になりそうなところ
– 変数名・関数名・クラス構造 その他もろもろ– JSON でデータ返したら camel case 一致してない
• C#/VB → Upper Camel Case, JSON → snake_case– Ajax で表示更新を実装したら cshtml と JavaScript コード
に似たような HTML 記述ができている– コントローラーに async メソッドとそうでないメソッドが混
在
コントローラー内の async メソッドの必要性
• メソッド内で IO 処理を並列にするなど await 呼び出しを使う必要がなければ不要
• by @shibayan(ASP.NET MVP)
アプリが完成したら• ニュースリリースを送る
– 「リツイート直後のツイートを表示するやつは」GIGAZINE とねとらぼ に送付
• Web アプリを紹介するサイトに登録
まとめ• プロジェクトの構成
– ルーティング,コントローラー,ビュー• モデルの操作
– Code First, コントローラーとビューの生成• ユーザー認証
– 実装・用意されている仕組み,カスタマイズ方法• Azure Web アプリへ発行• その他の機能の実装方法など
以上で…
• サインインユーザーだけがイベント情報を登録/編集できるサイト
• 登録時に情報をツイートする機能• …というようなサイトは作れるかも
ご清聴ありがとうございました
2015/4/11ASP.NET 初心者勉強会@jz5(プロ生)