[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]] -[[戻る>ASP.NET MVC]] * 目次 [#xe5726ff] #contents *概要 [#h6dc5730] *MVC [#o92da354] MVCの基本的な考え方 **M(Model)に実装される処理 [#a1340f52] Modelには、 -B層クラスと、 -B層クラスが返すViewに渡されるEntity, Bean, POCO的なクラス(ViewModel) がある。 **V(View)に実装される処理 [#ad9a7d3d] View = 画面表示のための処理。 -マスタページ的なViewと、 -全体View -部分Viewがある。 **C(Controller)に実装される処理 [#h99848ae] -Action Methodを実装する。 -Action Methodは、 ++「M(Model)」を呼び出して ++「(Bean≒M)」を取得して ++「V(View)」呼び出す。 **モジュールの作成順 [#g4c4867d] +C(Controller)を作成 +V(View)を作成 +M(Model)を作成 +C(Controller)にAction Methodを追加し、C→M→Vと繋げる。 *C(Controller)関連 [#g454069b] **URL ルーティング [#abe121d3] -あらかじめ定義されたルート定義 (URLのパターン) に従い、~ URLからControllerやAction Methodに処理を振り分けること。 -ユーザーがブラウザーに URL を入力すると、~ 定義されているルーティング規則を使用してURL が解析され、~ Controllerのパスが特定される。 -例えば、ASP.NET MVCでは、RouteConfig.cs / .vb ファイルにデフォルトで~ 以下のようにルーティングが定義されている。~ (このルート定義は、自由にカスタマイズ可能) routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); この時、ブラウザから http://server/applicationname/Products/Index/1 というURLでリクエストを送信した場合、 http://(Server FQDN名)/(Controller名)/(Action Method名)/(id 値) ルート定義に従い、ページハンドラは -Controller名:Products -Action Method名:Index -id (Action Methodに渡す値):1 と判断し、 Products Controllerの Index Action Methodを呼び出し、Action Methodの引数として "1" を渡す。~ Action Method名と id 値は省略可能で、Action Method名を省略すると、Index Action Methodが実行される。 -ASP.NET MVC アプリケーションのコントローラーとアクション メソッド~ https://msdn.microsoft.com/ja-jp/library/dd410269.aspx **Action Method [#w8313d08] ***リクエストデータと引数の関連付け [#i5d9821b] マップの方法 -パラメタ名と一致した引数を定義~ POST や GET のパラメタの名前と一致した引数を定義しておけば、自動的にマップされる。 --Get ならクエリ文字列のキー名 --Post ならフォームデータのキー名 -FormCollection を使う (Post の場合のみ)~ <form> の中身がコレクション型として保持されたもの。 -Modelクラスを使う (Post の場合のみ)~ ControllerとViewで、Modelクラスのデータを双方向バインディングしている場合に使用される。~ (双方向バインディングについては、[[HTMLヘルパー>#r27d7319]]を参照。) ***戻り値 [#pcb22e7a] Action Methodの結果として、Action Resultを返す。~ 詳細は[[Action Result>#q3d2aae4]]を参照。 **非同期Controller [#lc319892] -ASP.NET MVC での非同期コントローラーの使用~ https://msdn.microsoft.com/ja-jp/library/ee728598.aspx --非同期Controllerを使用すると、[[async/await]]を使用し、~ Webサーバのスレッド枯渇を防ぐことができる。 --実行に時間のかかる CPU バインド以外の要求に非同期Controllerを使用すると、~ Webサーバの待機スレッドを他に転用可能になるので、Webサーバのスレッド数を節約し、~ スレッド枯渇による「HTTP 503 (サーバーがビジー状態です。)」を防止できる。 --図から、リクエスト処理開始時とレスポンス処理終了時のスレッドが変わることが解る。~ 後のスレッドは独立したスレッドプールから取得する。複雑なのでオーバーヘッドがある。 ***旧(AsyncControllerを継承する。) [#hab6cbd4] -AsyncController を継承する。 -以下の命名規約を守ったAction Methodを定義する。 --ActionNameAsync --ActionNameCompleted(delegate) ***Task<ActionResult>を返す。 [#m0e7c5c6] MVC 4 以降であれば、以下のように書ける。 -Action Method内部でTaskを使用する場合、 public Task<ActionResult> Index() -Action Method内部でasync/await キーワードを使う場合、 public async Task<ActionResult> Index() ***参考 [#c1c3ca5f] -非同期コントローラを使ってみた - しばやん雑記~ http://blog.shibayan.jp/entry/20100715/1279204349 -ASP.NET MVC 4 の新機能、タスク対応の非同期コントローラを使う - しばやん雑記~ http://blog.shibayan.jp/entry/20111105/1320495813 **Action Result [#q3d2aae4] Controller のAction Methodは、View の選択と指示として、~ [[ActionResult>https://msdn.microsoft.com/ja-jp/library/system.web.mvc.actionresult.aspx]] クラスのオブジェクトを返す必要がある。 Action Methodで、 return View(); と、Viewを指定しないoverloadで呼び出すと、 /Views/コントローラ名/アクション名.cshtml を呼び出す。 ***ActionResultの種類とヘルパー・メソッド [#o5927f4e] ActionResult クラスには、以下の種類が存在する。 |種類|概要・用途|コード例(ヘルパー・メソッド)|h |ViewResult|指定された全体 View の表示を指示する。&br();基本的には [[HTML.BeginForm>#y7008c56]] の場合に使用する。|return View("Result");&br();("Result" は全体 View 名)| |PartialViewResult|指定された部分 View の表示を指示する。&br();基本的には [[Ajax.BeginForm>#b0eaca55]] の場合に使用する。|return PartialView("Result");&br();("Result" は部分 View 名)| |RedirectResult|指定した URL にリダイレクトする場合に使用する。|return Redirect("http://www.wings.msn.to/");| |RedirectToActionResult|指定した Controller, Action にリダイレクトする場合に使用する。|return RedirectToAction("Index");| |~|指定したルート名にリダイレクトする場合に使用する。|return RedirectToRoute("View Product", new { ProductName = <商品名> });| |FilePathResult|指定されたパスの内容をファイルとして出力|return File("C:\temp\file.zip", "application/zip", "file.zip");| |FileContentResult|byte配列の内容をファイルとして出力|return File(bytes, "application/pdf");| |FileStreamResult|ストリームの内容をファイルとして出力|return new FileStreamResult(fileStream, "application/pdf");| |ContentResult|プレーン・テキストを出力(Ajax通信)|Return Content("こんにちは、世界!", "text/plain");| |JsonResult|指定されたコンテンツをJSONとして出力(Ajax通信)|return Json(JsonConvert.SerializeObject(result), JsonRequestBehavior.AllowGet);| |JavaScriptResult|指定されたコンテンツをJavaScriptスクリプトとして出力|return JavaScript(code);| |HttpUnauthorizedResult|承認の失敗時にHTTP応答コード「401 Unauthorized」をセット|-| |EmptyResult|何もしない|-| -c# - RedirectToAction and RedirectToRoute - Stack Overflow~ http://stackoverflow.com/questions/8944355/redirecttoaction-and-redirecttoroute -参考 --ActionResult クラス~ https://msdn.microsoft.com/ja-jp/library/system.web.mvc.actionresult.aspx --ASP.NET MVC ActionResultの派生型 | 宇宙仮面の研究室~ https://uchukamen.wordpress.com/2011/02/06/asp-net-mvc-actionresult%E3%81%AE%E6%B4%BE%E7%94%9F%E5%9E%8B/ --連載:ASP.NET MVC入門:第3回~ ActionResultオブジェクトでアクション操作も自由自在 - @IT~ --- (1/5)~ http://www.atmarkit.co.jp/ait/articles/0907/10/news109.html --- ~ (5/5)~ http://www.atmarkit.co.jp/ait/articles/0907/10/news109_5.html ***HttpStatusCodeResult [#e8677bb1] Viewではなく、HTTP状態コードを返す。 -System.Web.Mvc.HttpStatusCodeResult~ https://msdn.microsoft.com/ja-jp/library/system.web.mvc.httpstatuscoderesult.aspx --System.Web.Mvc.HttpNotFoundResult --System.Web.Mvc.HttpUnauthorizedResult *V(View)関連 [#h3fb6308] **ビューエンジン [#z40de977] Webページのビューエンジンには以下の2つのものがある。 ***ASPX [#u5044497] 従来の ASP.NET と同様、~ 式やコードブロックを コード・ナゲット(<% ~ %>)で囲む記述形式。~ View の拡張子も、従来の ASP.NET と同様、「*.aspx」で表される。 ***Razor(主流) [#id4ef38b] ASP.NET MVC 3 で登場したビューエンジン。~ 式やコードブロックの先頭に「@」を付与する記述形式で、~ 冗長なコード・ナゲット(<% ~ %>)が不要になる。~ View の拡張子は、C# の場合は「*.cshtml」、VB の場合は「*.vbhtml」で表される。 ***参考 [#kb9c52d6] -C# Razor構文 基礎文法 総まとめ - @IT~ http://www.atmarkit.co.jp/fdotnet/rapidmaster/rapidmaster_03/rapidmaster_03.html -第5回 新しいビュー・エンジン「Razor」の基本を理解しよう - @IT~ http://www.atmarkit.co.jp/fdotnet/aspnetmvc3/aspnetmvc3_06/aspnetmvc3_06_01.html -ASP.NET MVC 3 開発入門 (12) - Razor の文法 - しばやん雑記~ http://blog.shibayan.jp/entry/20110317/1300294985 -ASP.NET MVC のビューは ASPX ではなく Razor を~ http://miso-soup3.hateblo.jp/entry/2013/12/02/030906 **Viewヘルパー [#r27d7319] 従来の ASP.NET では、ASP.NET Web コントロールを使用して、~ ラベルやテキストボックスなどのコントロールを表示していたが、 -ASP.NET MVC では Viewヘルパーを使用する。 ***主な Viewヘルパー [#v09eb480] ASP.NET MVC では、主に以下のような Viewヘルパーが使用できる。 -表示のためのViewヘルパー |項番|HTMLタグ|Viewヘルパー|h |1|データの表示|Html.DisplayFor| |2|入力可能なデータの表示|Html.EditorFor| |3|ラベルの表示1|Html.DisplayNameFor| |4|ラベルの表示2|Html.LabelFor| -HTMLタグに対応したViewヘルパー |項番|HTMLタグ|Viewヘルパー|h |1|フォーム <form>|Html.BeginForm または Ajax.BeginForm| |2|リンク <a>|Html.ActionLink| |3|テキストボックス <input type="text">|Html.TextBox または Html.TextBoxFor| |4|テキストエリア <textarea>|Html.TextArea または Html.TextAreaFor| |5|パスワード <input type="password">|Html.Password または Html.PasswordFor| |6|チェックボックス <input type="checkbox">|Html.CheckBox または Html.CheckBoxFor| |7|ドロップダウンリスト <select>|Html.DropDownList または Html.DropDownListFor| |8|リストボックス <select>|Html.ListBox または Html.ListBoxFor| |9|ラジオボタン <input type="radio">|Html.RadioButton または Html.RadioButtonFor| |10|隠しフィールド <input type="hidden">|Html.Hidden または Html.HiddenFor| -URL生成 |項番|HTMLタグ|Viewヘルパー|h |1|「~/...」を仮想パスに変換|Url.Content| |2|Controller、ActionMethod名などから仮想パスを生成|Url.Action| |3|RouteValueDictionaryから仮想パスを生成|Url.RouteUrl| -なお、ボタンを生成する Viewヘルパーはないため、~ 直接 <input type="button"> または <input type="submit"> を記述する。 ***2種類のHTMLヘルパー [#o7472bbe] Html.xxxx と Html.xxxxFor の2種類のHTMLヘルパーがある。 -Html.xxxx~ ''Model から View への一方向バインディング''。~ Html.TextBox("Category") のように、~ プロパティを文字列でマップ指定する場合は、~ "For" がつかない HTMLヘルパーを使用する。 -Html.xxxxFor~ ''Model ⇔ View の双方向バインディング''。 --...Forという名称のHTMLヘルパーは、ViewとModelの間での双方向バインディングを行う。 --Html.TextBoxFor(model => model.Category) のように、~ プロパティをラムダ式でマップ指定する場合は、"For" で終わる HTMLヘルパーを使用する。 >ただし、HTTP を経由しての双方向バインディングになるので、~ 処理方式的には、以下のような処理シーケンスになる。 --POST 時に、Html.TextBoxFor などへの入力値を、自動的に Model に復元する。 --Controller は、復元された Model から情報を取得して処理を行う。 **マスターページ [#ycd23a70] ヘッダーやフッター、サイドメニューなどをアプリケーションで共通的に表示させたい場合、~ マスターページを使用してレイアウトを共通化させることができる。~ マスターページには、画面ごとに個別実装が必要な箇所を定義する。 ***ビューエンジン [#g5621ed9] -ビューエンジンが ASPX の場合は、従来の ASP.NET と同様 ContentPlaceHolder を使用する。 -ビューエンジンが Razor の場合は、RenderBody を使用してメインのコンテンツ領域を定義する。 ***配置場所と使用方法 [#hed3f79f] -アプリケーション共通 --配置場所 ---/View/Shared/_Layout.cshtml --使用方法 ---/View/Shared/_ViewStart.cshtml のLayoutプロパティ経由で呼び出される。 -View単位 --配置場所 ---/View/Shared/_XXXXLayout.cshtml --使用方法 ---/View/Controller名/YYYY.cshtml のLayoutプロパティ経由で呼び出される。 ---Viewヘルパー・メソッドの第二引数にLayoutスクリプト名を指定する。 return View("Viewスクリプト名", "Layoutスクリプト名"); ***マスターページへのセクションの定義 [#x99b0c9c] メインのコンテンツ領域以外に、画面ごとに個別実装が必要な箇所を定義する場合、~ RenderSection を使用して「セクション」と呼ばれるサブのコンテンツ領域を定義する。 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <!-- メインのコンテンツ領域を描画する場所を定義 --> @RenderBody() @Scripts.Render("~/bundles/jquery") <!-- セクション (サブのコンテンツ領域) を描画する場所を定義 --> @RenderSection("scripts", required: false) </body> </html> ***コンテンツページの実装 [#j06a55f0] -例えば、上記のようにマスターページを定義した場合、~ 各コンテンツページでは以下のように実装する。 @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; // 使用するマスターページを指定 } @* メインのコンテンツ領域 *@ <h2>Index</h2> @* セクション (サブのコンテンツ領域) *@ @section scripts{ <script type="text/javascript"> ... </script> } -上記のように、セクションを実装する場合、 --C# の場合は「@section <セクション名> { ~ }」、 --VB の場合は「@Section <セクション名> ~ End Section」 >で囲む必要がある。 **BeginForm [#se7ba00c] BeginFormには以下の2つのものがある。 ***Html.BeginFormの特徴 [#w59fdfea] -従来のASPなどでも採用されていたMVC方式を同じ仕組み。 -リクエスト・レスポンスの度に、画面全体を再描画する。 -ViewState相当の状態保存処理を独自実装する必要がある。 ***Ajax.BeginFormの特徴 [#mb6e9e4d] -クライアント・サイドのJavaScriptフレームワークとシームレスに連動して部分更新を実現する仕組み。 -Html.BeginFormとモジュール構造は大きく変わらない。ただし、以下のようにHtml.BeginFormと動作は大きく異なる。 --jQueryを使用してリクエストし、 --更新部位のレスポンスを受けてJavaScriptで描画。 -部分更新のターゲットを意識する必要がある。 --送信時に設定したターゲット以外を更新する場合、画面遷移をする場合、~ JavaScriptを返して更新や画面遷移をする必要がある。 -参考 --連載:ASP.NET MVC入門:第3回~ ActionResultオブジェクトでアクション操作も自由自在 (4-5) - @IT~ http://www.atmarkit.co.jp/ait/articles/0907/10/news109_4.html >その性質上、Ajax通信の結果をページの一部に反映させるようなケースで利用することになるだろう。 *M(Model)関連 [#ue2c093c] **ViewBag, ViewData, TempData [#m41f8886] ControllerからViewにデータを渡すときに使用する入れ物的なモノ。 -参考 --ViewData vs ViewBag vs TempData - 夜になったら寝る~ http://kyabatalian.hatenablog.com/entry/2015/12/05/232504 ***ViewBag [#z43ab48b] -ViewBag は dynamic object。 ***ViewData [#qe522f71] -ViewData は Dictionary。 ***TempData [#i059f7bd] -TempData は Dictionary。 -TempData は保持されるため、リダイレクト先に値を渡したいときなどに使う。 *検証機能 [#za7f960c] **Model側 [#qd38a035] ModelState・・・ -Method --ModelState.IsValid --ModelState.AddModelError **View側 [#za24022f] -Method --Html.ValidationSummary~ すべての検証結果のエラー メッセージを要約 --Html.ValidationMessage~ 検証結果のエラー メッセージ --Html.ValidationMessageFor~ 検証結果のエラー メッセージ -CSS --validation-summary-errors~ ValidationSummaryメソッドによって出力されたメッセージの<div>要素(エラー有) --validation-summary-valid~ ValidationSummaryメソッドによって出力されたメッセージの<div>要素(エラー無) --field-validation-error~ ValidationMessageメソッドによって出力されたメッセージの<span>要素(エラー有) --field-validation-valid~ ValidationMessageメソッドによって出力されたメッセージの<span>要素(エラー無) --input-validation-error~ 検証エラーが発生した要素 *スキャフォールディング [#e701b267] **概要 [#g794a3ae] スキャフォールディング(Scaffolding)。~ 日本語で「足場」、「骨組み」の意味。 -M(Model)を元に、 --C(Controller) ---CRUDを行うAction Method --V(View) >を自動で生成する機能。 -通常、 --CRUDのAction Methodだけが自動生成される。 --ADO.NET [[Entity Framework]] によるデータ操作を行う場合、~ Action Methodに加えて View も自動生成できる。 -その他 --[[WebFormでもサポートされている>http://blog.shibayan.jp/entry/20130219/1361281202]]。 **M(Model) [#d93a335a] -使用するModelを選択する。 -Modelの新規作成も可能 **C(Controller) [#jf4991ce] -M(Model)の複数形 + Controllerという名称になる。 -Action Method --Index --Details --Create --Edit --Delete **V(View) [#te3ce747] -[[Entity Framework]] を使用すると、以下のようにViewまで自動生成される。 -また、[[Entity Framework]] を使用しない場合、個別に、~ Model指定したView追加(スキャフォールディング)ができる。 |項番|View名|対応するAction Method名|使用されるTemplate名|h |1|Index.cshtml|Index|List| |2|Details.cshtml|Details|Details| |3|Create.cshtml|Create|Create| |4|Edit.cshtml|Edit|Edit| |5|Delete.cshtml|Delete|Delete| *[[ADO.NET Entity Framework のコードファースト機能>Entity Framework]] [#zb82cea5] *ASP.NET MVC 4 の新機能 [#b06c540b] **プロジェクトテンプレートの追加 [#k159317d] テンプレートが追加された。 -Facebook キャンバスアプリを簡単に作成するための「Facebookアプリケーション」テンプレート -シングルページ アプリケーションを作成するための「シングル ページ アプリケーション」 -,etc. **モバイルデバイス対応 [#gae80c09] ASP.NET MVC 4 で追加された「モバイル アプリケーション」テンプレートを使用して、モバイルデバイス向けアプリケーションを作成できる。このテンプレートでは、jQuery Mobile をベースとしており、タッチ操作に最適化した UI を構築できる。 -複数ブラウザに対応させるためのディスプレイモード --xxx.cshtml (PC 向け) --xxx.Mobile.cshtml (一般的なモバイル向け) --xxx.iPhone.cshtml (iPhone 向け) --その他 **複数ブラウザに対応させるためのディスプレイモード [#i6400115] ASP.NET MVC のディスプレイモードを利用すると、PC 向けサイト、モバイル向けサイトのように、ブラウザに応じてレイアウトを変えることができる。ディスプレイモードは、Global.asax の Application_Start メソッドに定義することで使用できる。~ 例えば、iPhone 向けのディスプレイモードを定義したい場合は、以下のように実装する。 protected void Application_Start() { (中略) DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone") { ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) >= 0) }); } この時、通常の「Index.cshtml」と同じフォルダに「Index.''iPhone''.cshtml」を作成し、iPhone 向けのレイアウトを定義すると、 http://server/application/Controller/Index/id という同じ URL に対し、PC のブラウザからアクセスした場合は「Index.cshtml」が使用され、iPhone からアクセスした場合は「Index.''iPhone''.cshtml」が使用されるようになる。 **Web API [#s5b3bcda] RESTful な HTTP サービスを構築するためのフレームワーク。~ 既定では、以下のようにルーティングが定義されている。 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); したがって、Web API のAction Methodを呼び出す際の URL は以下のようになる。 http://server/application/Controller/id ASP.NET MVC と違い、Web API のルート定義にはAction Methodの指定がない。 Web API を使用した場合、リクエストの HTTP メソッドに応じて、~ 以下のようにControllerのAction Methodが自動的に呼び出される。 |項番|HTTP メソッド|呼び出されるメソッド|h |1|GET|"Get" で始まる名前のメソッド| |2|POST|"Post" で始まる名前のメソッド| |3|PUT|"Put" で始まる名前のメソッド| |4|DELETE|"Delete" で始まる名前のメソッド| Web API を利用した場合のコントローラの例を以下に示す。同じコントローラの中で GET に対応したメソッドを複数定義したい場合などは、以下のようにオーバーロードで対応できる。 public class ValuesController : ApiController { // GET api/values public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/values/5 public string Get(int id) { return "value"; } // POST api/values public void Post([FromBody]string value) { } // PUT api/values/5 public void Put(int id, [FromBody]string value) { } // DELETE api/values/5 public void Delete(int id) { } } **OAuth / OpenID 対応 [#z14b0107] ASP.NET MVC 4 の「インターネット アプリケーション」テンプレートを使用すると、OAuth/OpenId を使用した Facebook / Twitter / Google / Microsoft などのアカウントによる認証が可能となる。~ これらのアカウントによる認証を行う場合は、App_Start フォルダの AuthConfig クラスで設定を記述する。 public static void RegisterAuth() { OAuthWebSecurity.RegisterFacebookClient( appId: "", appSecret: ""); } Microsoft.Web.WebPages.OAuth.OAuthWebSecurity クラスには、~ 各サービスに応じて、アカウント認証を行うためのメソッドが用意されている。 |項番|メソッド|処理内容|h |1|RegisterFacebookClient|Facebook アカウントによる認証| |2|RegisterGoogleClient|Google アカウントによる認証| |3|RegisterLinkedInClient|LinkedIn アカウントによる認証| |4|RegisterMicrosoftClient|Microsoft アカウントによる認証| |5|RegisterTwitterClient|Twitter アカウントによる認証| |6|RegisterYahooClient|Yahoo アカウントによる認証| **シングルページ アプリケーション [#i6c5037c] 単一ページで構成される Ajax アプリケーション。~ HTML5 / CSS や、各種 JavaScript ライブラリを使用することで、UX の向上、マルチデバイス対応が可能となる。~ シングルページ アプリケーションでは、クライアントサイドは各種 JavaScript ライブラリを使用してデータ操作を行い、サーバサイドは Web API を使用して RESTful にAction Methodを実行する。~ 「シングル ページ アプリケーション」テンプレートを使用すると、既定で以下の JavaScript ライブラリが使用できる。 |項番|JavaScript ライブラリ|説明|h |1|jQuery|JavaScript のコーディングを支援するライブラリ| |2|jQuery UI|jQuery をベースとした UI ライブラリ| |3|jQuery Validate|HTML フォームの入力検証を行う jQuery プラグイン| |4|knockout.js|JavaScript による MVVM (Model-View-ViewModel) フレームワーク| |5|modernizr.js|HTML5/CSS のブラウザ対応状況を調査するためのライブラリ| ---- Tags: [[:ASP.NET MVC]]