ASP.NET Web ページ (Razor) のサイト全体の動作のカスタマイズ
作成者: Tom FitzMacken
この記事では、ASP.NET Web ページ (Razor) サイトでページのサイト側設定を行う方法について説明します。
ここでは、次の内容について学習します。
- サイト内のすべてのページの値 (グローバル値またはヘルパー設定) を設定するコードの実行方法。
- フォルダー内のすべてのページの値を設定するコードの実行方法。
- ページの読み込み前後にコードを実行する方法。
- 中央のエラー ページにエラーを送信する方法。
- フォルダー内のすべてのページに認証を追加する方法。
チュートリアルで使用するソフトウェアのバージョン
- ASP.NET Web ページ (Razor) 2
- WebMatrix 3
- ASP.NET Web ヘルパー ライブラリ (NuGet パッケージ)
このチュートリアルは、ASP.NET Web ヘルパー ライブラリを使用できないという点を除けば、ASP.NET Web ページ 3 および Visual Studio 2013 (または Visual Studio Express 2013 for Web) でも動作します。
ASP.NET Web ページの Web サイト スタートアップ コードの追加
ASP.NET Web ページで記述する多くのコードでは、個々のページに、そのページに必要なすべてのコードを含めることができます。 たとえば、あるページでメール メッセージを送信する場合、その操作に関するすべてのコードを 1 つのページに記述することが可能です。 これには、メールの送信 (つまり、SMTP サーバー用) 設定とメール メッセージの送信設定を初期化するコードも含めることができます。
ただし、場合によっては、サイト上のページを実行する前に、いくつかのコードを実行した方がよい場合があります。 これは、サイト内のどの場所でも使用できる値 ("グローバル値" という) の設定に役立ちます。たとえば、一部のヘルパーでは、メール設定やアカウント キーなどの値を指定する必要があります。 これらの設定をグローバル値で保持できれば便利です。
これは、サイトのルートに _AppStart.cshtml という名前のページを作成して行うことができます。 このページが存在する場合は、サイト内の任意のページが最初に要求されたときに実行されます。 そのため、グローバル値を設定するコードを実行するのに適した場所といえます。 (_AppStart.cshtml にはアンダースコア プレフィックスがあるため、ユーザーが直接要求した場合でも、ASP.NET はこのページをブラウザーに送信しません)。
次の図は、_AppStart.cshtml ページの仕組みを示しています。 ページに対する要求を受け取ると、これがサイト内の任意のページに対する最初の要求である場合、ASP.NET はまず _AppStart.cshtml ページが存在するかどうかをチェックします。 存在する場合、_AppStart.cshtml ページ内のコードが実行され、その後、要求されたページが実行されます。
Web サイトのグローバル値の設定
WebMatrix サイトのルート フォルダーに、_AppStart.cshtml という名前のファイルを作成します。 このファイルはサイトのルートにある必要があります。
既存のコンテンツを次に置き換えます。
@{ AppState["customAppName"] = "Application Name"; }
このコードは値を
AppState
ディクショナリに格納します。この値は、サイト内のすべてのページで自動的に使用できます。 _AppStart.cshtml ファイルには、マークアップが含まれていないことに注意してください。 ページでコードが実行され、その後、最初に要求されたページにリダイレクトされます。Note
_AppStart.cshtml ファイルにコードを記述する場合は注意が必要です。 _AppStart.cshtml ファイルのコードでエラーが発生した場合には、Web サイトは起動しません。
ルート フォルダーに、AppName.cshtml という名前の新しいページを作成します。
デフォルトのマークアップとコードを次のように置き換えます。
<!DOCTYPE html> <html> <head> <title>Show Application Name</title> </head> <body> <h1>@AppState["customAppName"]</h1> </body> </html>
このコードは、_AppStart.cshtml ページで設定した
AppState
オブジェクトから値を抽出します。ブラウザーで AppName.cshtml ページを実行します。 (実行する前に、ファイル ワークスペース内でこのページが選択されていることを確認してください)。ページにグローバル値が表示されます。
ヘルパーの値の設定
_AppStart.cshtml ファイルに適した活用方法として、サイトで使用し初期化する必要のあるヘルパーの値の設定があります。 典型的な例としては、WebMail
ヘルパーのメール設定と、ReCaptcha
ヘルパーの秘密キーと公開キーがあります。 このようなケースでは、_AppStart.cshtml で値を 1 回設定すれば、サイト内のすべてのページでその値が設定済みになります。
この手順では、WebMail
設定をグローバルに設定する方法を示します。 (WebMail
ヘルパーの使用方法の詳細については、「ASP.NET Web ページ サイトへのメールの追加」を参照してください)。
「ASP.NET Web ページ サイトへのヘルパーのインストール」で説明されているように、(まだ追加していない場合は) ASP.NET Web ヘルパー ライブラリを Web サイトに追加します。
_AppStart.cshtml ファイルがまだない場合は、Web サイトのルート フォルダーに _AppStart.cshtml という名前でファイルを作成します。
_AppStart.cshtml ファイルに次の
WebMail
設定を追加します。@{ // Initialize WebMail helper WebMail.SmtpServer = "your-SMTP-host"; WebMail.SmtpPort = 25; WebMail.UserName = "your-user-name-here"; WebMail.Password = "your-account-password"; WebMail.From = "your-email-address-here"; }
コード内の次の電子メール関連の設定を変更します。
your-SMTP-host
をアクセス権を持つ SMTP サーバーの名前に設定します。your-user-name-here
を SMTP サーバー アカウントのユーザー名に設定します。your-account-password
を SMTP サーバー アカウントのパスワードに設定します。your-email-address-here
を自分のメール アドレスに設定します。 これは、メッセージの送信元の電子メール アドレスです。 (一部のメール プロバイダーでは、別のFrom
アドレスを指定できないため、ユーザー名をFrom
アドレスとして使用します)。SMTP 設定の詳細については、「ASP.NET Web ページ (Razor) サイトからのメールの送信」記事の「メール設定の構成」および「ASP.NET Web ページ (Razor) のトラブルシューティング ガイド」の「メール送信に関する問題」を参照してください。
_AppStart.cshtml ファイルを保存して閉じます。
Web サイトのルート フォルダーに、TestEmail.cshtml という名前で新しいページを作成します。
既存のコンテンツを次に置き換えます。
@{ var message = ""; try{ if(IsPost){ WebMail.Send( to: Request.Form["emailAddress"], subject: Request.Form["emailSubject"], body:Request.Form["emailBody"] ); message = "Email sent!"; } } catch(Exception ex){ message = "Email could not be sent!"; } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Test Email</title> </head> <body> <h1>Test Email</h1> <form method="post"> <p> <label for="emailAddress">Email address:</label> <input type="text" name="emailAddress" /> </p> <p> <label for="emailSubject">Subject:</label> <input type="text" name="emailSubject" /> </p> <p> <label for="emailBody">Text to send:</label><br/> <textarea name="emailBody" rows="6"></textarea> </p> <p><input type="submit" value="Send!" /></p> @if(IsPost){ <p>@message</p> } </form> </body> </html>
ブラウザーで TestEmail.cshtml ページを実行します。
自身にメール メッセージを送信するためのフィールドに入力して、[送信] をクリックします。
メールをチェックして、メッセージを受け取ったことを確認します。
この例で重要なのは、SMTP サーバーの名前やメールの資格情報など、通常は変更することのない設定を _AppStart.cshtml ファイルで設定していることです。 こうすることで、メールを送信する各ページで、この設定を再度行う必要がありません。 (何らかの理由でこれらの設定を変更する必要がある場合には、ページで個別に設定できます)。このページでは、受信者やメール メッセージの本文など、通常、毎回変更する値のみを設定します。
フォルダー内のファイル実行前後のコードの実行
_AppStart.cshtml を使用して、サイト内のページを実行する前のコードを記述できるのと同様に、特定のフォルダーのページ実行前 (および後) に実行されるコードを記述できます。 これは、フォルダー内のすべてのページに同じレイアウト ページを設定する場合や、フォルダー内のページを実行する前にユーザーがログインしているかをチェックする場合に役立ちます。
特定のフォルダー内のページの場合は、_PageStart.cshtml という名前のファイルにコードを作成できます。 次の図は、_PageStart.cshtml ページの仕組みを示しています。 ページに対する要求を受け取ると、ASP.NET はまず _AppStart.cshtml ページを確認し、そのページを実行します。 次に、ASP.NET は _PageStart.cshtml ページが存在するかどうかを チェックし、存在する場合は実行します。 その後、要求されたページを実行します。
_PageStart.cshtml ページ内に、RunPage
メソッドを含めることで、処理中に、要求されたページを実行する場所を指定することができます。 これにより、コードを実行してから要求されたページを実行し、その後でさらにコードを実行できます。 RunPage
を含めない場合は、_PageStart.cshtml 内のすべてのコードが実行され、その後、要求されたページが自動的に実行されます。
ASP.NET では、_PageStart.cshtml ファイルの階層を作成できます。 _PageStart.cshtml ファイルは、サイトのルートと任意のサブフォルダーに配置できます。 ページが要求されると、 最上位レベルの (サイトのルートに最も近い) _PageStart.cshtml ファイルが実行され、次いで、次のサブフォルダーの _PageStart.cshtml ファイルが実行されというふうに、要求されたページを含むフォルダーに要求が到達するまでサブフォルダー構造の下位に移動していきます。 該当するすべての _PageStart.cshtml ファイルが実行された後に、要求されたページが実行されます。
たとえば、次の _PageStart.cshtml ファイルと Default.cshtml ファイルの組み合わせがあるとします。
@* ~/_PageStart.cshtml *@
@{
PageData["Color1"] = "Red";
PageData["Color2"] = "Blue";
}
@* ~/myfolder/_PageStart.cshtml *@
@{
PageData["Color2"] = "Yellow";
PageData["Color3"] = "Green";
}
@* ~/myfolder/default.cshtml *@
@PageData["Color1"]
<br/>
@PageData["Color2"]
<br/>
@PageData["Color3"]
/myfolder/default.cshtml を実行すると、次の内容が表示されます。
Red
Yellow
Green
フォルダー内のすべてのページに対する初期化コードの実行
_PageStart.cshtml ファイルに適した活用方法として、1 つのフォルダー内のすべてのファイルの同じレイアウト ページを初期化することがあります。
ルート フォルダーに、InitPages という名前で新しいフォルダーを作成します。
Web サイトの InitPages フォルダーに、_PageStart.cshtml という名前のファイルを作成し、デフォルトのマークアップとコードを次のように置き換えます。
@{ // Sets the layout page for all pages in the folder. Layout = "~/Shared/_Layout1.cshtml"; // Sets a variable available to all pages in the folder. PageData["MyBackground"] = "Yellow"; }
Web サイトのルートに、Shared という名前のフォルダーを作成します。
Shared フォルダーに、_Layout1.cshtml という名前のファイルを作成し、デフォルトのマークアップとコードを次のように置き換えます。
@{ var backgroundColor = PageData["MyBackground"]; } <!DOCTYPE html> <html> <head> <title>Page Title</title> <link type="text/css" href="/Styles/Site.css" rel="stylesheet" /> </head> <body> <div id="header"> Using the _PageStart.cshtml file </div> <div id="main" style="background-color:@backgroundColor"> @RenderBody() </div> <div id="footer"> © 2012 Contoso. All rights reserved </div> </body> </html>
InitPages フォルダーに、Content1.cshtml という名前のファイルを作成し、既存の内容を次のように置き換えます。
<p>This is content page 1.</p>
InitPages フォルダーに、Content2.cshtml という名前の別のファイルを作成し、デフォルトのマークアップを次のように置き換えます。
<p>This is content page 2.</p>
ブラウザーで Content1.cshtml を実行します。
Content1.cshtml ページを実行すると、_PageStart.cshtml ファイルによって
Layout
が設定されるとともに、PageData["MyBackground"]
が色に設定されます。 Content1.cshtml では、レイアウトと色を適用します。ブラウザーに Content2.cshtml を表示します。
どちらのページも、_PageStart.cshtml で初期化された同じレイアウト ページと色を使用するため、同じレイアウトになります。
_PageStart.cshtml を使用したエラー処理
_PageStart.cshtml ファイルのもう 1 つの良い活用方法は、フォルダー内の .cshtml ページで発生し得るプログラミング エラー (例外) を処理する方法を作り出すことです。 以下の例により、その 1 つの方法を示します。
ルート フォルダーに InitCatch という名前のフォルダーを作成します。
Web サイトの InitCatch フォルダーに、_PageStart.cshtml という名前のファイルを作成し、既存のマークアップとコードを次のように置き換えます。
@{ try { RunPage(); } catch (Exception ex) { Response.Redirect("~/Error.cshtml?source=" + HttpUtility.UrlEncode(Request.AppRelativeCurrentExecutionFilePath)); } }
このコードでは、
try
ブロック内でRunPage
メソッドを呼び出して、明示的に要求されたページの実行を試みます。 要求されたページで何らかのプログラミング エラーが発生した場合には、catch
ブロック内のコードが実行されます。 このケースでは、コードによりページ (Error.cshtml) にリダイレクトされ、URL の一部としてエラーが発生したファイルの名前が渡されます。 (ページはすぐに作成されます)。Web サイトの InitCatch フォルダーに、Exception.cshtml という名前のファイルを作成し、既存のマークアップとコードを次のように置き換えます。
@{ var db = Database.Open("invalidDatabaseFile"); }
この例の目的に沿って、このページで行っているのは、存在しないデータベース ファイルを開こうとすることで、意図的にエラーを発生させることです。
ルート フォルダーに Error.cshtml という名前のファイルを作成し、既存のマークアップとコードを次のように置き換えます。
<!DOCTYPE html> <html> <head> <title>Error Page</title> </head> <body> <h1>Error report</h1> <p>An error occurred while running the following file: @Request["source"]</p> </body> </html>
このページでは、式
@Request["source"]
が URL から値を取得して表示します。ツール バーの [保存] をクリックします。
ブラウザーで Exception.cshtml を実行します。
Exception.cshtml でエラーが発生するため、_PageStart.cshtml ページにより Error.cshtml ファイルにリダイレクトされ、メッセージが表示されます。
例外の詳細については、「Razor 構文を使用した ASP.NET Web ページのプログラミングの概要」を参照してください。
_PageStart.cshtml を使用したフォルダー アクセスの制限
_PageStart.cshtml ファイルを使用して、フォルダー内のすべてのファイルへのアクセスを制限することもできます。
WebMatrix で、[テンプレートからサイト] オプションを使用して新しい Web サイトを作成します。
使用可能なテンプレートから、[スターター サイト] を選択します。
ルート フォルダーに AuthenticatedContent という名前のフォルダーを作成します。
AuthenticatedContent フォルダーに、_PageStart.cshtml という名前のファイルを作成し、既存のマークアップとコードを次のように置き換えます。
@{ Response.CacheControl = "no-cache"; if (!WebSecurity.IsAuthenticated) { var returnUrl = "~/Account/Login?ReturnUrl=" + Request.Url.LocalPath; Response.Redirect(returnUrl); } }
このコードは、フォルダー内のすべてのファイルをキャッシュさせないようにすることから始まります。 (これは、1 人のユーザーのキャッシュされたページを次のユーザーに使用させたくない、パブリック コンピューターなどのシナリオで必要です)。次に、このコードではフォルダー内のページを表示させる前に、ユーザーがサイトにサインインしたかどうかを判断します。 ユーザーがサインインしていない場合、コードによりログイン ページにリダイレクトされます。
ReturnUrl
という名前のクエリ文字列値を含めている場合は、ログイン ページは、最初に要求されたページにユーザーを返すことができます。AuthenticatedContent フォルダーに Page.cshtml という名前で新しいページを作成します。
デフォルトのマークアップを次のように置き換えます。
@{ Layout = "~/_SiteLayout.cshtml"; Page.Title = "Authenticated Content"; } <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> Thank you for authenticating! </body> </html>
ブラウザーで Page.cshtml を実行します。 コードにより、ユーザーはログイン ページにリダイレクトされます。 ログインには登録が必要です。 登録してログインすると、ページに移動してその内容を表示できます。