Customizing Site-Wide Behavior for ASP.NET Web Pages (Razor) Sites
By Tom FitzMacken|February 17, 2014
 

This article explains how to make site-side settings for pages in an ASP.NET Web Pages (Razor) website.

What you'll learn:

  • How to run code that lets you set values (global values or helper settings) for all pages in a site.
  • How to run code that lets you set values for all pages in a folder.
  • How to run code before and after a page loads.
  • How to send errors to a central error page.
  • How to add authentication to all pages in a folder.

Software versions used in the tutorial

Adding Website Startup Code for ASP.NET Web Pages

For much of the code that you write in ASP.NET Web Pages, an individual page can contain all the code that's required for that page. For example, if a page sends an email message, it's possible to put all the code for that operation in a single page. This can include the code to initialize the settings for sending email (that is, for the SMTP server) and for sending the email message.

However, in some situations, you might want to run some code before any page on the site runs. This is useful for setting values that can be used anywhere in the site (referred to as global values.)  For example, some helpers require you to provide values like email settings or account keys. It can be handy to keep these settings in global values.

You can do this by creating a page named _AppStart.cshtml in the root of the site. If this page exists, it runs the first time any page in the site is requested. Therefore, it's a good place to run code to set global values. (Because_AppStart.cshtml has an underscore prefix, ASP.NET won't send the page to a browser even if users request it directly.)

The following diagram shows how the _AppStart.cshtml page works. When a request comes in for a page, and if this is the first request for any page in the site, ASP.NET first checks whether a _AppStart.cshtml page exists. If so, any code in the _AppStart.cshtml page runs, and then the requested page runs.

Setting Global Values for Your Website

  1. In the root folder of a WebMatrix website, create a file named _AppStart.cshtml. The file must be in the root of the site.
  2. Replace the existing content with the following:
    @{
      AppState["customAppName"] = "Application Name";
    }

    This code stores a value in the AppState dictionary, which is automatically available to all pages in the site. Notice that the _AppStart.cshtml file does not have any markup in it. The page will run the code and then redirect to the page that was originally requested.

    Note       Be careful when you put code in the _AppStart.cshtml file.     If any errors occur in code in the _AppStart.cshtml file, the website won't start.

  3. In the root folder, create a new page named AppName.cshtml.
  4. Replace the default markup and code with the following:
    <!DOCTYPE html>
    <html>
        <head>
            <title>Show Application Name</title>
        </head>
        <body>
            <h1>@AppState["customAppName"]</h1>
        </body>
    </html>

    This code extracts the value from the AppState object that you set in the _AppStart.cshtml page.

  5. Run the AppName.cshtml page in a browser. (Make sure the page is selected in the Files workspace before you run it.) The page displays the global value.

Setting Values for Helpers

A good use for the _AppStart.cshtml file is to set values for helpers that you use in your site and that have to be initialized. Typical examples are email settings for the WebMail helper and the private and public keys for theReCaptcha helper. In cases like these, you can set the values once in the _AppStart.cshtml and then they're already set for all the pages in your site.

This procedure shows you how to set WebMail settings globally. (For more information about using the WebMailhelper, see Adding Email to an ASP.NET Web Pages Site.)

  1. Add the ASP.NET Web Helpers Library to your website as described in Installing Helpers in an ASP.NET Web Pages Site, if you haven't already added it.
  2. If you don't already have a _AppStart.cshtml file, in the root folder of a website create a file named_AppStart.cshtml.
  3. Add the following WebMail settings to the _AppStart.cshtml file:
    @{
        // 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";
    }

    Modify the following email related settings in the code:

    • Set your-SMTP-host to the name of the SMTP server that you have access to.
    • Set your-user-name-here to the user name for your SMTP server account.
    • Set your-account-password to the password for your SMTP server account.
    • Set your-email-address-here to your own email address. This is the email address that the message is sent from. (Some email providers don't let you specify a different From address and will use your user name as the From address.)

    For more information about SMTP settings, see Configuring Email Settings in the article Sending Email from an ASP.NET Web Pages (Razor) Site and Issues with Sending Email in the ASP.NET Web Pages (Razor) Troubleshooting Guide.

  4. Save the _AppStart.cshtml file and close it.
  5. In the root folder of a website, create new page named TestEmail.cshtml.
  6. Replace the existing content with the following:
    @{
        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. Run the TestEmail.cshtml page in a browser.
  8. Fill in the fields to send yourself an email message and then click Send.
  9. Check your email to make sure you've gotten the message.

The important part of this example is that the settings that you don't usually change — like the name of your SMTP server and your email credentials — are set in the _AppStart.cshtml file. That way you don't need to set them again in each page where you send email. (Although if for some reason you need to change those settings, you can set them individually in a page.) In the page, you only set the values that typically change each time, like the recipient and the body of the email message.

Running Code Before and After Files in a Folder

Just like you can use _AppStart.cshtml to write code before pages in the site run, you can write code that runs before (and after) any page in a particular folder run. This is useful for things like setting the same layout page for all the pages in a folder, or for checking that a user is logged in before running a page in the folder.

For pages in particular folders, you can create code in a file named _PageStart.cshtml. The following diagram shows how the _PageStart.cshtml page works. When a request comes in for a page, ASP.NET first checks for a_AppStart.cshtml page and runs that. Then ASP.NET checks whether there's a _PageStart.cshtml page, and if so, runs that. It then runs the requested page.

Inside the _PageStart.cshtml page, you can specify where during processing you want the requested page to run by including a RunPage method. This lets you run code before the requested page runs and then again after it. If you don't include RunPage, all the code in _PageStart.cshtml runs, and then the requested page runs automatically.

ASP.NET lets you create a hierarchy of _PageStart.cshtml files. You can put a _PageStart.cshtml file in the root of the site and in any subfolder. When a page is requested, the _PageStart.cshtml file at the top-most level (nearest to the site root) runs, followed by the _PageStart.cshtml file in the next subfolder, and so on down the subfolder structure until the request reaches the folder that contains the requested page. After all the applicable _PageStart.cshtml files have run, the requested page runs.

For example, you might have the following combination of _PageStart.cshtml files and Default.cshtml file:

@* ~/_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"]

When you run /myfolder/default.cshtml, you'll see the following:

Red

Yellow

Green

Running Initialization Code for All Pages in a Folder

A good use for _PageStart.cshtml files is to initialize the same layout page for all files in a single folder.

  1. In the root folder, create a new folder named InitPages.
  2. In the InitPages folder of your website, create a file named _PageStart.cshtml and replace the default markup and code with the following:
    @{
        // 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. In the root of the website, create a folder named Shared.
  4. In the Shared folder, create a file named _Layout1.cshtml and replace the default markup and code with the following:
    @{
      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. In the InitPages folder, create a file named Content1.cshtml and replace the existing content with the following:
    <p>This is content page 1.</p>
  6. In the InitPages folder, create another file named Content2.cshtml and replace the default markup with the following:
    <p>This is content page 2.</p>
  7. Run Content1.cshtml in a browser.

    When the Content1.cshtml page runs, the _PageStart.cshtml file sets Layout and also setsPageData["MyBackground"] to a color. In Content1.cshtml, the layout and color are applied.

  8. Display Content2.cshtml in a browser.

    The layout is the same, because both pages use the same layout page and color as initialized in_PageStart.cshtml.

Using _PageStart.cshtml to Handle Errors

Another good use for the _PageStart.cshtml file is to create a way to handle programming errors (exceptions) that might occur in any .cshtml page in a folder. This example shows you one way to do this.

  1. In the root folder, create a folder named InitCatch.
  2. In the InitCatch folder of your website, create a file named _PageStart.cshtml and replace the existing markup and code with the following:
    @{
        try
        {
            RunPage();
        }
        catch (Exception ex)
        {
            Response.Redirect("~/Error.cshtml?source=" +
                HttpUtility.UrlEncode(Request.AppRelativeCurrentExecutionFilePath));
        }
    }

    In this code, you try running the requested page explicitly by calling the RunPage method inside a try block. If any programming errors occur in the requested page, the code inside the catch block runs. In this case, the code redirects to a page (Error.cshtml) and passes the name of the file that experienced the error as part of the URL. (You'll create the page shortly.)

  3. In the InitCatch folder of your website, create a file named Exception.cshtml and replace the existing markup and code with the following:
    @{
        var db = Database.Open("invalidDatabaseFile");
    }

    For purposes of this example, what you're doing in this page is deliberately creating an error by trying to open a database file that doesn't exist.

  4. In the root folder, create a file named Error.cshtml and replace the existing markup and code with the following:
    <!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>

    In this page, the expression @Request["source"] gets the value out of the URL and displays it.

  5. In the toolbar, click Save.
  6. Run Exception.cshtml in a browser.

    Because an error occurs in Exception.cshtml, the _PageStart.cshtml page redirects to the Error.cshtml file, which displays the message.

    For more information about exceptions, see   Introduction to ASP.NET Web Pages Programming Using the Razor Syntax.

Using _PageStart.cshtml to Restrict Folder Access

You can also use the _PageStart.cshtml file to restrict access to all the files in a folder.

  1. In WebMatrix, create a new website using the Site From Template option.
  2. From the available templates, select Starter Site.
  3. In the root folder, create a folder named AuthenticatedContent.
  4. In the AuthenticatedContent folder, create a file named _PageStart.cshtml and replace the existing markup and code with the following:
    @{
        Response.CacheControl = "no-cache";
        if (!WebSecurity.IsAuthenticated) {
            var returnUrl = "~/Account/Login?ReturnUrl=" + Request.Url.LocalPath;
            Response.Redirect(returnUrl);
        }
    }

    The code starts by preventing all files in the folder from being cached. (This is required for scenarios like public computers, where you don't want one user's cached pages to be available to the next user.) Next, the code determines whether the user has signed in to the site before they can view any of the pages in the folder. If the user is not signed in, the code redirects to the login page. The login page can return the user to the page that was originally requested if you include a query string value named ReturnUrl.

  5. Create a new page in the AuthenticatedContent folder named Page.cshtml.
  6. Replace the default markup with the following:
    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Authenticated Content";
    }
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
      </head>
      <body>
        Thank you for authenticating!
      </body>
    </html>
  7. Run Page.cshtml in a browser. The code redirects you to a login page. You must register before logging in. After you've registered and logged in, you can navigate to the page and view its contents.

_AppStart.cshtml 和 _PageStart.cshtml的妙用的更多相关文章

  1. _appstart.cshtml,_pagestart.cshtml,_viewstart.cshtml

    ASP.NET MVC3 系列教程 – Web Pages 1.0 I:Web Pages 1.0中以"_"开头的特别文件(文件命名时不区分大小写) "_appstart ...

  2. ASP.NET MVC3 系列教程 – Web Pages 1.0

    http://www.cnblogs.com/highend/archive/2011/04/14/aspnet_mvc3_web_pages.html I:Web Pages 1.0中以“_”开头的 ...

  3. Customizing Site-Wide Behavior for ASP.NET Web Pages (Razor) Sites

    Customizing Site-Wide Behavior for ASP.NET Web Pages (Razor) Sites By Tom FitzMacken|February 17, 20 ...

  4. 了解.net mvc实现原理ActionResult/View

    了解.net mvc实现原理ActionResult/View 上一篇了解了请求至Controller的Action过程,这篇继续看源码处理Action收到请求数据再返回ActionResult到Vi ...

  5. PartialViewResult不鸟_ViewStart.cshtml

    概述 在ASP.NET MVC中,对于Action中得到的ActionResult如果是一个ViewResult对象,那么在进行View呈现时,则会先执行_ViewStart.cshtml,然后再去执 ...

  6. _viewstart.cshtml的作用

    在ASP.NET MVC 3.0及更高版本中,用Razor模板引擎新建项目后,Views目录下会出现一个这样的文件:_ViewStart.cshtml. _viewstart.cshtml的作用 1. ...

  7. MVC| Razor 布局-模板页 | ViewStart.cshtml

    来自:http://blog.csdn.net/fanbin168/article/details/49725175 这个图就看明白了 _ViewStart.cshtml 视图文件的作用  _View ...

  8. Asp.Net Core 入门(五)—— 布局视图_Layout.cshtml

    布局视图和我们在Asp.Net MVC一样,布局视图_Layout.cshtml使得所有视图保持一致的外观变得更加容易,因为我们只有一个要修改的布局视图文件,更改后将立即反映在整个应用程序的所有视图中 ...

  9. ASP.NET MVC教程八:_ViewStart.cshtml

    一.引言 _ViewStart.cshtml是在ASP.NET MVC 3.0及更高版本以后出现的,用Razor模板引擎新建项目后,Views目录下面会出现一个这样的文件: 打开_ViewStart. ...

随机推荐

  1. 使用.NET Remoting开发分布式应用——基于租约的生存期

    一.概述 知名类型的SingleCall对象可以在客户程序的方法调用之后被垃圾收集器清理掉,因为它没有保持状态,属于无状态的.而客户激活的类型的对象和知名类型的SingleTon对象都属于生存期长的对 ...

  2. c#学习笔记 VS编辑器常用设置

    1.NET Framework 4.0安装好后目录在哪里? C:\Windows\Microsoft.NET\Framework下面 C#中CLR和IL分别是什么含义? CLR common lang ...

  3. 6 字典和集合——《Swift3.0从入门到出家》

    字典和集合 字典 字典是集合类型存放多个键值对,其中键是唯一的,不能重复 字典中存放的键值对是无序的,写入的顺序和读取的顺序可能不同 字典中存放的数据是任意类型 字典可以分为可变字典和不可变字典 创建 ...

  4. Visual Studio Code如何调试代码

    首先安装扩展调试插件debugger for chrome 点击瓢虫按钮,进行调试项目的配置,点击配置按钮 选择Chrome环境, 会弹出Chrome调试配置文件launch.json,修改下端口即可 ...

  5. TI c6657开发资源

    TI 官方论坛:英文  中文 http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index.html http://e ...

  6. 使用Tomcat+Redis来实现集群部署中的Session共享问题

    一.工作中因为要使用到Tomcat集群部署,此时就涉及到了Session共享问题,主要有三种解决方案: 1.使用数据库来存储Session 2.使用Cookie来存储Session 3.使用Redis ...

  7. U-boot分析与移植(2)----U-boot stage1分析

    我们要生成u-boot.bin文件,它首先依赖于很多.o文件和.lds链接脚本文件 我们只要找到对应的.lds链接脚本文件就可以分析u-boot的启动流程. 1.打开u-boot-1.1.6\u-bo ...

  8. List和Map常用的几种遍历方式

    遍历一个List有以下几种方法: /*//1.普通for循环的方式: List<String> list=new ArrayList<String>(); list.add(& ...

  9. Py修行路 python基础 (四)运算 copy

    字符串的格式化 在字符串中插入 %s ,作为占位符,后边儿再定义插入变量. 算术运算 % 取模   判断奇偶数 / 除法   有小于号 // 取整除  返回整数部分 逻辑运算 and or not ' ...

  10. 如何规避javascript多人开发函数重名问题

    命名空间 封闭空间 js模块化mvc(数据层.表现层.控制层) seajs(如果了解的呢,可以说) 变量转换成对象的属性 对象化