自訂 ASP.NET 網頁 (Razor) 網站的網站範圍行為
演講者:Tom FitzMacken
本文介紹如何對 ASP.NET 網頁 (Razor) 網站中的頁面進行網站端設定。
您將學到什麼:
- 如何執行程式碼來為網站中的所有頁面設定值 (全域值或協助程式設定)。
- 如何執行允許您為資料夾中的所有頁面設定值的程式碼。
- 如何在頁面載入之前和之後執行程式碼。
- 如何將錯誤傳送到中央錯誤頁面。
- 如何在資料夾中的所有頁面中新增身份驗證。
教學中使用的軟體版本
- ASP.NET 網頁 (Razor) 2
- WebMatrix 3
- ASP.NET Web Helpers 程式庫 (NuGet 套件)
本教學也適用於 ASP.NET 網頁 3 和 Visual Studio 2013 (或 Visual Studio Express 2013 for Web),但您不能使用 ASP.NET Web Helpers 程式庫。
為 ASP.NET 網頁新增網站啟動程式碼
對於您在 ASP.NET 網頁中編寫的大部分程式碼,單一頁面可以包含該頁面所需的所有程式碼。 例如,如果頁面發送電子郵件訊息,則可以將該操作的所有程式碼放在單一頁面中。 這可以包括用於初始化發送電子郵件 (即 SMTP 伺服器) 和發送電子郵件訊息的設定的代碼。
但是,在某些情況下,您可能希望在網站上的任何頁面執行之前執行一些程式碼。 這對於設定可在網站中的任何位置使用的值 (稱為全域值) 非常有用。例如,某些協助幫助程式要求您提供電子郵件設定或帳戶金鑰等值。 將這些設定保留為全域值會很方便。
您可以透過在網站根目錄中建立一個名為 _AppStart.cshtml 的頁面來完成此操作。 如果此頁面存在,它將在第一次請求網站中的任何頁面時執行。 因此,這是執行程式碼來設定全域值的好地方。 (因為 _AppStart.cshtml 有下劃線前綴,所以即使使用者直接要求,ASP.NET 也不會將該頁面傳送到瀏覽器。)
下圖顯示了 _AppStart.cshtml 頁面的工作原理。 當收到頁面請求時,如果這是網站中任何頁面的第一個請求,則 ASP.NET 首先檢查 _AppStart.cshtml 頁面是否存在。 如果是這樣,則執行 _AppStart.cshtml 頁面中的任何程式碼,然後執行請求的頁面。
為您的網站設定全域值
在 WebMatrix 網站的根資料夾中,建立一個名為 _AppStart.cshtml 的檔案。 該檔案必須位於網站的根目錄中。
將現有內容替換為以下內容:
@{ AppState["customAppName"] = "Application Name"; }
此程式碼在
AppState
字典中儲存一個值,該值自動可供網站中的所有頁面使用。 請注意,_AppStart.cshtml 檔案中沒有任何標記。 該頁面將執行程式碼,然後重定向到最初請求的頁面。注意
將程式碼放入 _AppStart.cshtml 檔案時要小心。 如果 _AppStart.cshtml 檔案中的程式碼出現任何錯誤,網站將無法啟動。
在根資料夾中,建立一個名為 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 中設定一次值,然後它們就已經為網站中的所有頁面設定了。
此過程向您展示如何進行全域 WebMail
設定。 (有關使用 WebMail
協助程式的詳細資訊,請參閱將電子郵件新增至 ASP.NET 網頁網站。)
如果尚未新增 ASP.NET Web Helpers 程式庫,請依照在 ASP.NET 網頁網站中安裝說明程式中所述將其新增至您的網站。
如果您還沒有 _AppStart.cshtml 文件,請在網站的根資料夾中建立一個名為 _AppStart.cshtml 的文件。
將以下
WebMail
設定新增至 _AppStart.cshtml 檔案:@{ // 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 網頁 (Razor) 網站發送電子郵件一文中的設定電子郵件設定和 ASP.NET 網頁(Razor) 故障排除指南中的發送電子郵件問題。
儲存 _AppStart.cshtml 檔案並關閉它。
在網站的根資料夾中,建立名為 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 檔案的一個很好的用途是為單一資料夾中的所有檔案初始化相同的佈局頁面。
在根資料夾中,建立一個名為 InitPages 的新資料夾。
在網站的 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"; }
在網站的根目錄中,建立一個名為 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 檔案的另一個很好的用途是建立一種方法來處理資料夾中任何 .cshtml 頁面中可能發生的程式錯誤 (例外)。 此範例向您展示了一種執行此操作的方法。
在根資料夾中,建立一個名為 InitCatch 的資料夾。
在網站的 InitCatch 資料夾中,建立一個名為 _PageStart.cshtml 的文件,並將現有標記和程式碼替換為以下內容:
@{ try { RunPage(); } catch (Exception ex) { Response.Redirect("~/Error.cshtml?source=" + HttpUtility.UrlEncode(Request.AppRelativeCurrentExecutionFilePath)); } }
在此程式碼中,您嘗試透過呼叫
try
區塊內的RunPage
方法來明確地執行請求的頁面。 如果請求的頁面中發生任何編程錯誤,則catch
區塊內的程式碼將執行。 在本例中,程式碼重新導向至頁面 (Error.cshtml) 並將遇到錯誤的檔案的名稱作為 URL 的一部分傳遞。 (您很快就會建立該頁面。)在網站的 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 網頁編程簡介。
使用 _PageStart.cshtml 限制資料夾訪問
您也可以使用 _PageStart.cshtml 檔案來限制對資料夾中所有檔案的存取。
在 WebMatrix 中,使用來自範本的網站選項建立新網站。
從可用範本中,選擇起始站點。
在根資料夾中,建立一個名為 AuthenticatedContent 的資料夾。
在 AuthenticatedContent 資料夾中,建立一個名為 _PageStart.cshtml 的文件,並將現有標記和程式碼替換為以下內容:
@{ Response.CacheControl = "no-cache"; if (!WebSecurity.IsAuthenticated) { var returnUrl = "~/Account/Login?ReturnUrl=" + Request.Url.LocalPath; Response.Redirect(returnUrl); } }
該程式碼首先阻止快取資料夾中的所有檔案。 (這對於公共電腦等場景是必需的,在這種情況下,您不希望一個使用者的快取頁面可供下一個使用者使用。) 接下來,程式碼確定使用者是否已登入該站點,然後才能查看任何頁面。 如果使用者未登入,程式碼將重定向到登入頁面。 如果您包含名為
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。 該程式碼會將您重新導向到登入頁面。 您必須在登入前註冊。 註冊並登入後,您可以導航到該頁面並查看其內容。