自定义 ASP.NET 网页 (Razor) 网站的Site-Wide行为

作者 Tom FitzMacken

本文介绍如何为 ASP.NET 网页 (Razor) 网站中的页面创建网站端设置。

学习内容:

  • 如何运行代码,以便为网站中的所有页面设置值 (全局值或帮助程序设置) 。
  • 如何运行允许你为文件夹中所有页面设置值的代码。
  • 如何在页面加载之前和之后运行代码。
  • 如何将错误发送到中心错误页。
  • 如何将身份验证添加到文件夹中的所有页面。

本教程中使用的软件版本

  • ASP.NET 网页 (Razor) 2
  • WebMatrix 3
  • ASP.NET Web 帮助程序库 (NuGet 包)

本教程也适用于 ASP.NET 网页 3 以及 Visual Studio 2013 (或 Visual Studio Express 2013 for Web) ,但不能使用 ASP.NET Web 帮助程序库。

为 ASP.NET 网页 添加网站启动代码

对于在 ASP.NET 网页 中编写的大部分代码,单个页面可以包含该页所需的所有代码。 例如,如果页面发送电子邮件,可以将该操作的所有代码放在单个页面中。 这可以包括用于初始化用于发送电子邮件 (设置的代码,即 SMTP 服务器) 和发送电子邮件设置。

但是,在某些情况下,你可能希望在站点上的任何页面运行之前运行一些代码。 这对于设置可在网站中的任何位置使用的值非常有用, (称为 全局值。) 例如,某些帮助程序要求您提供电子邮件设置或帐户密钥等值。 将这些设置保存在全局值中可能很方便。

为此,可以在网站的根目录中创建名为 _AppStart.cshtml 的页面。 如果此页面存在,它将在首次请求网站中的任何页面时运行。 因此,它是运行代码来设置全局值的好地方。 (由于 _AppStart.cshtml 具有下划线前缀,因此即使用户直接请求,ASP.NET 也不会将页面发送到浏览器。)

下图显示了 _AppStart.cshtml 页的工作原理。 当请求传入页面时,如果这是网站中任何页面的第一个请求,ASP.NET 首先检查 是否存在 _AppStart.cshtml 页面。 如果是这样, _AppStart.cshtml 页中的任何代码将运行,然后请求的页面运行。

[图像显示 App Star dot CSHTML 的工作原理。]

设置网站的全局值

  1. 在 WebMatrix 网站的根文件夹中,创建名为 _AppStart.cshtml 的文件。 文件必须位于站点的根目录中。

  2. 将现有内容替换为以下内容:

    @{
      AppState["customAppName"] = "Application Name";
    }
    

    此代码将值存储在字典中 AppState ,该字典自动可供网站中的所有页面使用。 请注意, _AppStart.cshtml 文件没有任何标记。 页面将运行代码,然后重定向到最初请求的页面。

    注意

    将代码放入 _AppStart.cshtml 文件时要小心。 如果 _AppStart.cshtml 文件中的代码中出现任何错误,则网站不会启动。

  3. 在根文件夹中,创建名为 AppName.cshtml 的新页面。

  4. 将默认标记和代码替换为以下内容:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Show Application Name</title>
        </head>
        <body>
            <h1>@AppState["customAppName"]</h1>
        </body>
    </html>
    

    此代码从 AppState_AppStart.cshtml 页中设置的 对象中提取值。

  5. 在浏览器中运行 AppName.cshtml 页。 (在运行页面之前,请确保在 “文件” 工作区中选择该页。) 该页显示全局值。

    [屏幕截图显示显示全局值的页面。]

设置帮助程序的值

_AppStart.cshtml 文件的一个好用处是为站点中使用的且必须初始化的帮助程序设置值。 典型示例包括帮助程序的电子邮件设置 WebMail 以及帮助者的 ReCaptcha 私钥和公钥。 在这种情况下,可以在 _AppStart.cshtml 中设置一次值,然后已为网站中的所有页面设置这些值。

此过程演示如何全局设置 WebMail 设置。 (有关使用WebMail帮助程序的详细信息,请参阅向 ASP.NET 网页 Site 添加Email。)

  1. 如在 ASP.NET 网页网站中安装帮助程序中所述,将 ASP.NET Web 帮助程序库添加到网站(如果尚未添加)。

  2. 如果还没有 _AppStart.cshtml 文件,请在网站的根文件夹中创建一个名为 _AppStart.cshtml 的文件。

  3. 将以下 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) 站点发送Email和发送Email的问题一文中的配置Email设置

  4. 保存 _AppStart.cshtml 文件并将其关闭。

  5. 在网站的根文件夹中,创建名为 TestEmail.cshtml 的新页面。

  6. 将现有内容替换为以下内容:

    @{
        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>
    
  7. 在浏览器中运行 TestEmail.cshtml 页。

  8. 填写字段以向自己发送电子邮件,然后单击“ 发送”。

  9. 检查电子邮件,确保已收到该邮件。

此示例的重要部分是,通常不会更改的设置(如 SMTP 服务器的名称和电子邮件凭据)在 _AppStart.cshtml 文件中设置。 这样就不需要在发送电子邮件的每个页面中再次设置它们。 (如果出于某种原因需要更改这些设置,则可以在 page 中单独设置它们。) 在页面中,仅设置通常每次更改的值,如收件人和电子邮件正文。

在文件夹中运行文件之前和之后的代码

就像可以在网站中的页面运行之前使用 _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 的新文件夹。

  2. 在网站的 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";
    }
    
  3. 在网站的根目录中,创建名为 “共享”的文件夹

  4. “共享文件夹” 中,创建一个名为 _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">
      &copy; 2012 Contoso. All rights reserved
    </div>
    </body>
    </html>
    
  5. InitPages 文件夹中,创建名为 Content1.cshtml 的文件,并将现有内容替换为以下内容:

    <p>This is content page 1.</p>
    
  6. InitPages 文件夹中,创建另一个名为 Content2.cshtml 的文件,并将默认标记替换为以下内容:

    <p>This is content page 2.</p>
    
  7. 在浏览器中运行 Content1.cshtml

    [图像显示在浏览器中运行内容 1 点 CSHTML。]

    当 Content1.cshtml 页面运行时,_PageStart.cshtml 文件将设置Layout并设置为PageData["MyBackground"]颜色。 在 Content1.cshtml 中,应用布局和颜色。

  8. 在浏览器中显示 Content2.cshtml

    布局是相同的,因为两个页面使用的布局页面和颜色与 在 _PageStart.cshtml 中初始化的相同。

使用 _PageStart.cshtml 处理错误

_PageStart.cshtml 文件的另一个良好用途是创建一种处理编程错误的方法, (可能出现在文件夹中的任何 .cshtml 页面中的异常) 。 此示例演示了执行此操作的一种方法。

  1. 在根文件夹中,创建名为 InitCatch 的文件夹

  2. 在网站的 InitCatch 文件夹中,创建名为 _PageStart.cshtml 的文件,并将现有标记和代码替换为以下内容:

    @{
        try
        {
            RunPage();
        }
        catch (Exception ex)
        {
            Response.Redirect("~/Error.cshtml?source=" +
                HttpUtility.UrlEncode(Request.AppRelativeCurrentExecutionFilePath));
        }
    }
    

    在此代码中,尝试通过在 块内try调用 RunPage 方法来显式运行请求的页面。 如果请求的页面中发生任何编程错误,块内的代码将 catch 运行。 在这种情况下,代码会重定向到 error.cshtml) (页,并将遇到错误的文件的名称作为 URL 的一部分传递。 (你将很快创建页面。)

  3. 在网站的 InitCatch 文件夹中,创建名为 Exception.cshtml 的文件,并将现有标记和代码替换为以下内容:

    @{
        var db = Database.Open("invalidDatabaseFile");
    }
    

    就此示例而言,在本页中执行的操作是故意通过尝试打开不存在的数据库文件来创建错误。

  4. 在根文件夹中,创建名为 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 中获取值并显示该值。

  5. 在工具栏中,单击“ 保存”。

  6. 在浏览器中运行 Exception.cshtml

    [屏幕截图显示了在浏览器中运行异常点 CSHTML。]

    由于 Exception.cshtml 中发生错误, 因此_PageStart.cshtml 页将重定向到 Error.cshtml 文件,该文件将显示消息。

    有关异常的详细信息,请参阅使用 Razor 语法 ASP.NET 网页编程简介

使用 _PageStart.cshtml 限制文件夹访问

还可以使用 _PageStart.cshtml 文件来限制对文件夹中所有文件的访问。

  1. 在 WebMatrix 中,使用“ 从模板网站” 选项创建新网站。

  2. 在可用模板中,选择“ 初学者网站”。

  3. 在根文件夹中,创建名为 AuthenticatedContent 的文件夹

  4. AuthenticatedContent 文件夹中,创建一个名为 _PageStart.cshtml 的文件,并将现有标记和代码替换为以下内容:

    @{
        Response.CacheControl = "no-cache";
        if (!WebSecurity.IsAuthenticated) {
            var returnUrl = "~/Account/Login?ReturnUrl=" + Request.Url.LocalPath;
            Response.Redirect(returnUrl);
        }
    }
    

    代码首先阻止缓存文件夹中的所有文件。 (这是公共计算机等方案所必需的,其中不希望一个用户的缓存页面可供下一个用户使用。) Next,代码将确定用户是否已登录到网站,然后才能查看文件夹中的任何页面。 如果用户未登录,代码将重定向到登录页。 如果包含名为 ReturnUrl的查询字符串值,则登录页可以将用户返回到最初请求的页面。

  5. 在名为 Page.cshtmlAuthenticatedContent 文件夹中创建一个新页面。

  6. 将默认标记替换为以下内容:

    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Authenticated Content";
    }
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
      </head>
      <body>
        Thank you for authenticating!
      </body>
    </html>
    
  7. 在浏览器中运行 Page.cshtml 。 该代码会将你重定向到登录页。 在登录之前,必须注册。 注册并登录后,可以导航到页面并查看其内容。

其他资源

使用 Razor 语法 ASP.NET 网页编程简介