使用 Razor 语法 (C#) ASP.NET Web 编程简介

作者 Tom FitzMacken

本文概述了使用 Razor 语法通过 ASP.NET 网页 进行编程。 ASP.NET 是 Microsoft 用于在 Web 服务器上运行动态网页的技术。 本文重点介绍如何使用 C# 编程语言。

你将了解的内容

  • 使用 Razor 语法开始编程的前 8 个编程提示 ASP.NET 网页。
  • 你需要的基本编程概念。
  • ASP.NET 服务器代码和 Razor 语法的全部内容。

软件版本

  • ASP.NET 网页 (Razor) 3

本教程也适用于 ASP.NET 网页 2。

前 8 个编程提示

本部分列出了开始使用 Razor 语法编写 ASP.NET 服务器代码时绝对需要了解的一些提示。

注意

Razor 语法基于 C# 编程语言,这是最常用于 ASP.NET 网页的语言。 但是,Razor 语法也支持 Visual Basic 语言,你所看到的所有内容也可以在 Visual Basic 中执行。 有关详细信息,请参阅附录 Visual Basic 语言和语法

可以在本文后面找到有关其中大多数编程技术的更多详细信息。

1. 使用 @ 字符向页面添加代码

字符 @ 启动内联表达式、单语句块和多语句块:

<!-- Single statement blocks  -->
@{ var total = 7; }
@{ var myMessage = "Hello World"; }

<!-- Inline expressions -->
<p>The value of your account is: @total </p>
<p>The value of myMessage is: @myMessage</p>

<!-- Multi-statement block -->
@{
    var greeting = "Welcome to our site!";
    var weekDay = DateTime.Now.DayOfWeek;
    var greetingMessage = greeting + " Today is: " + weekDay;
}
<p>The greeting is: @greetingMessage</p>

当页面在浏览器中运行时,这些语句如下所示:

Razor-Img1

提示

HTML 编码

使用 @ 字符在页面中显示内容时,如前面的示例所示,ASP.NET 对输出进行 HTML 编码。 这会将保留的 HTML 字符 ((如 <>&) )替换为使字符在网页中显示为字符而不是解释为 HTML 标记或实体的代码。 如果没有 HTML 编码,服务器代码的输出可能无法正确显示,并且可能会使页面面临安全风险。

如果目标是输出将标记呈现为标记 ((例如 <p></p> 段落)或 <em></em> 强调文本) 的 HTML 标记,请参阅本文后面的 在代码块中组合文本、标记和代码 部分。

有关 HTML 编码的详细信息,请参阅 使用窗体

2.将代码块括在大括号中

代码块包含一个或多个代码语句,并用大括号括起来。

<!-- Single statement block.  -->
@{ var theMonth = DateTime.Now.Month; }
<p>The numeric value of the current month: @theMonth</p>

<!-- Multi-statement block. -->
@{
    var outsideTemp = 79;
    var weatherMessage = "Hello, it is " + outsideTemp + " degrees.";
}
<p>Today's weather: @weatherMessage</p>

浏览器中显示的结果:

Razor-Img2

3. 在 块中,用分号结束每个代码语句

在代码块内,每个完整的代码语句都必须以分号结尾。 内联表达式不以分号结尾。

<!-- Single-statement block -->
@{ var theMonth = DateTime.Now.Month; }

<!-- Multi-statement block -->
@{
    var outsideTemp = 79;
    var weatherMessage = "Hello, it is " + outsideTemp + " degrees.";
}

<!-- Inline expression, so no semicolon -->
<p>Today's weather: @weatherMessage</p>

4.使用变量存储值

可以将值存储在变量中,包括字符串、数字和日期等。使用 var 关键字 (keyword) 创建新变量。 可以使用 直接在页面中 @插入变量值。

<!-- Storing a string -->
@{ var welcomeMessage = "Welcome, new members!"; }
<p>@welcomeMessage</p>

<!-- Storing a date -->
@{ var year = DateTime.Now.Year; }

<!-- Displaying a variable -->
<p>Welcome to our new members who joined in @year!</p>

浏览器中显示的结果:

Razor-Img3

5.将文本字符串值括在双引号中

字符串是被视为文本的字符序列。 若要指定字符串,请将其括在双引号中:

@{ var myString = "This is a string literal"; }

如果要显示的字符串包含反斜杠字符 ( \ ) 或双引号 ( " ) ,请使用带有 @ 运算符前缀的逐字字符串文本。 (在 C# 中,除非使用逐字字符串 literal.)

<!-- Embedding a backslash in a string -->
@{ var myFilePath = @"C:\MyFolder\"; }
<p>The path is: @myFilePath</p>

若要嵌入双引号,请使用逐字字符串文本并重复引号:

<!-- Embedding double quotation marks in a string -->
@{ var myQuote = @"The person said: ""Hello, today is Monday."""; }
<p>@myQuote</p>

下面是在页面中使用这两个示例的结果:

Razor-Img4

注意

请注意, @ 字符既用于在 C# 中标记逐字字符串文本,也用于标记 ASP.NET 页中的代码。

6.代码区分大小写

在 C# 中,关键字 ((如 vartrueif) )和变量名称区分大小写。 以下代码行创建两个不同的变量, lastNameLastName.

@{
    var lastName = "Smith";
    var LastName = "Jones";
}

如果将变量声明为 var lastName = "Smith"; ,并尝试将页面中的变量引用为 @LastName,则会获取 值 "Jones" 而不是 "Smith"

注意

在 Visual Basic 中,关键字和变量 区分大小写。

7. 大部分编码都涉及对象

对象表示一个可以使用编程的内容-页面、文本框、文件、图像、Web 请求、电子邮件、客户记录 (数据库行) 等。对象具有描述其特征的属性,并且可以读取或更改这些属性:文本框对象具有Text属性 () ,请求对象具有 Url 属性,电子邮件具有 From 属性,客户对象具有 FirstName 属性。 对象还具有方法是它们可以执行的“谓词”。 示例包括文件对象的 Save 方法、图像对象的 Rotate 方法和电子邮件对象的 Send 方法。

通常,你将使用 Request 对象,它为你提供诸如页面上) 的文本框 (窗体字段的值、发出请求的浏览器类型、页面的 URL、用户标识等信息。以下示例演示如何访问 对象的属性 Request 以及如何调用 MapPath 对象的 方法 Request ,这为你提供了服务器上的页面的绝对路径:

<table border="1">
<tr>
    <td>Requested URL</td>
    <td>Relative Path</td>
    <td>Full Path</td>
    <td>HTTP Request Type</td>
</tr>
<tr>
    <td>@Request.Url</td>
    <td>@Request.FilePath</td>
    <td>@Request.MapPath(Request.FilePath)</td>
    <td>@Request.RequestType</td>
</tr>
</table>

浏览器中显示的结果:

Razor-Img5

8. 可以编写代码来做出决策

动态网页的一个关键功能是,可以根据条件确定要执行的操作。 执行此操作的最常见方法是使用 if 语句 (和可选的 else 语句) 。

@{
   var result = "";
   if(IsPost)
   {
      result = "This page was posted using the Submit button.";
   }
   else
   {
      result = "This was the first request for this page.";
   }
}

<!DOCTYPE html>
<html>
    <head>
        <title></title>
    </head>
<body>
<form method="POST" action="" >
  <input type="Submit" name="Submit" value="Submit"/>
  <p>@result</p>
</form>
</body>
</html>

语句 if(IsPost) 是编写 if(IsPost == true)的简写方式。 除了 if 语句,还有各种方法来测试条件、重复代码块等,本文稍后将对此进行介绍。

单击“ 提交 ”) 后,浏览器中显示的结果 (:

Razor-Img6

提示

HTTP GET 和 POST 方法以及 IsPost 属性

用于网页 (HTTP) 的协议支持 (用于向服务器发出请求的谓词) 方法数量非常有限。 最常见的两个是 GET(用于读取页面)和 POST(用于提交页面)。 通常,用户首次请求页面时,将使用 GET 请求页面。 如果用户填写表单,然后单击提交按钮,浏览器会向服务器发出 POST 请求。

在 Web 编程中,知道页面是作为 GET 还是 POST 请求,以便了解如何处理页面通常很有用。 在 ASP.NET 网页 中,可以使用 IsPost 属性查看请求是 GET 还是 POST。 如果请求是 POST,则 IsPost 属性将返回 true,你可以执行读取窗体上文本框的值等操作。 你将看到的许多示例演示如何根据 的值 IsPost以不同的方式处理页面。

简单的代码示例

此过程演示如何创建说明基本编程技术的页面。 在本示例中,创建一个允许用户输入两个数字的页面,然后添加它们并显示结果。

  1. 在编辑器中,创建一个新文件并将其命名为 AddNumbers.cshtml

  2. 将以下代码和标记复制到页面中,替换页面中已有的任何内容。

    @{
        var total = 0;
        var totalMessage = "";
        if(IsPost) {
    
            // Retrieve the numbers that the user entered.
            var num1 = Request["text1"];
            var num2 = Request["text2"];
    
            // Convert the entered strings into integers numbers and add.
            total = num1.AsInt() + num2.AsInt();
            totalMessage = "Total = " + total;
        }
    }
    
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>Add Numbers</title>
        <meta charset="utf-8" />
        <style type="text/css">
          body {background-color: beige; font-family: Verdana, Arial;
                margin: 50px; }
          form {padding: 10px; border-style: solid; width: 250px;}
        </style>
      </head>
    <body>
      <p>Enter two whole numbers and then click <strong>Add</strong>.</p>
      <form action="" method="post">
        <p><label for="text1">First Number:</label>
          <input type="text" name="text1" />
        </p>
        <p><label for="text2">Second Number:</label>
          <input type="text" name="text2" />
        </p>
        <p><input type="submit" value="Add" /></p>
      </form>
    
      <p>@totalMessage</p>
    
    </body>
    </html>
    

    下面是需要注意的一些事项:

    • 字符 @ 启动页面中的第一个代码块,并在嵌入页面底部附近的变量之前 totalMessage
    • 页面顶部的块用大括号括起来。
    • 在顶部的 块中,所有行都以分号结尾。
    • 变量 totalnum1num2totalMessage 存储多个数字和一个字符串。
    • 分配给 totalMessage 变量的文本字符串值用双引号引起来。
    • 由于代码区分大小写,因此在 totalMessage 页面底部附近使用该变量时,其名称必须与顶部的变量完全匹配。
    • 表达式 num1.AsInt() + num2.AsInt() 演示如何使用对象和方法。 AsInt每个变量上的 方法将用户输入的字符串转换为数字 (整数) ,以便您可以对其执行算术。
    • 标记 <form> 包含属性 method="post" 。 这指定当用户单击“ 添加”时,将使用 HTTP POST 方法将页面发送到服务器。 提交页面时,测试的 if(IsPost) 计算结果为 true,条件代码运行,显示添加数字的结果。
  3. 保存页面并在浏览器中运行它。 (请确保在“ 文件” 工作区中选中该页面,然后再运行它。) 输入两个整数,然后单击“ 添加 ”按钮。

    Razor-Img7

基本编程概念

本文概述了 ASP.NET Web 编程。 这不是一个详尽的检查,只是快速浏览你将最常使用的编程概念。 即便如此,它几乎涵盖了开始使用 ASP.NET 网页所需的一切。

但首先,有点技术背景。

Razor 语法、服务器代码和 ASP.NET

Razor 语法是一种简单的编程语法,用于在网页中嵌入基于服务器的代码。 在使用 Razor 语法的网页中,有两种内容:客户端内容和服务器代码。 客户端内容是你在网页中习惯的内容:HTML 标记 (元素) 、样式信息(如 CSS)以及某些客户端脚本(如 JavaScript)和纯文本。

Razor 语法允许向此客户端内容添加服务器代码。 如果页面中包含服务器代码,则服务器会先运行该代码,然后再将页面发送到浏览器。 通过在服务器上运行,代码可以执行单独使用客户端内容要复杂得多的任务,例如访问基于服务器的数据库。 最重要的是,服务器代码可以动态创建客户端内容, 它可以动态生成 HTML 标记或其他内容,然后将其连同页面可能包含的任何静态 HTML 一起发送到浏览器。 从浏览器的角度来看,服务器代码生成的客户端内容与任何其他客户端内容没有什么不同。 如你所见,所需的服务器代码非常简单。

包含 Razor 语法 ASP.NET 网页具有特殊文件扩展名 (.cshtml.vbhtml) 。 服务器识别这些扩展,运行用 Razor 语法标记的代码,然后将页面发送到浏览器。

ASP.NET 适合在哪里?

Razor 语法基于 Microsoft ASP.NET 的技术,而该技术又基于 Microsoft .NET Framework。 The.NET 框架是 Microsoft 提供的一个大型综合性编程框架,用于开发几乎任何类型的计算机应用程序。 ASP.NET 是专门用于创建 Web 应用程序的.NET Framework的一部分。 开发人员已使用 ASP.NET 来创建世界上许多规模最大、流量最高的网站。 (每当看到文件扩展名 .aspx 作为网站 URL 的一部分时,你就会知道该网站是使用 ASP.NET.)

Razor 语法为你提供 ASP.NET 的所有功能,但使用简化的语法,如果你是初学者,则更容易学习,如果你是专家,这会使你更高效。 尽管此语法易于使用,但它与 ASP.NET 和.NET Framework的系列关系意味着,随着网站变得越来越复杂,你拥有更大的框架的强大功能。

Razor-Img8

提示

类和实例

ASP.NET 服务器代码使用对象,这些对象又基于类的概念构建。 类是 对象的定义或模板。 例如,应用程序可能包含定义 Customer 任何客户对象所需的属性和方法的类。

当应用程序需要使用实际客户信息时,它会创建 (实例或实例 ) 客户对象。 每个单独的客户都是 类的 Customer 单独实例。 每个实例都支持相同的属性和方法,但每个实例的属性值通常不同,因为每个客户对象都是唯一的。 在一个客户对象中 LastName ,属性可能是“Smith”;在另一个客户对象中 LastName ,该属性可能是“Jones”。

同样,网站中的任何单个网页都是 Page 作为 类的实例的对象 Page 。 页面上的按钮是作为 Button 类的实例的对象 Button ,依此类而论。 每个实例都有自己的特征,但它们都基于对象的类定义中指定的内容。

基本语法

之前,你看到了有关如何创建 ASP.NET 网页页以及如何将服务器代码添加到 HTML 标记的基本示例。 在这里,你将了解使用 Razor 语法(即编程语言规则)编写 ASP.NET 服务器代码的基础知识。

如果你对编程 (有经验,尤其是当你使用过 C、C++、C#、Visual Basic 或 JavaScript) 时,你在此处阅读的大部分内容都会很熟悉。 你可能只需要熟悉如何将服务器代码添加到 .cshtml 文件中的标记。

在代码块中组合文本、标记和代码

在服务器代码块中,通常需要将文本或标记输出 (或两者) 到页面。 如果服务器代码块包含的文本不是代码,而应按原样呈现,ASP.NET 需要能够区分该文本与代码。 有多种方法可实现此目的。

  • 将文本括在 HTML 元素中,如 <p></p><em></em>

    @if(IsPost) {
        // This line has all content between matched <p> tags.
        <p>Hello, the time is @DateTime.Now and this page is a postback!</p>
    } else {
        // All content between matched tags, followed by server code.
        <p>Hello <em>stranger</em>, today is: <br /> </p>  @DateTime.Now
    }
    

    HTML 元素可以包含文本、其他 HTML 元素和服务器代码表达式。 例如 <p> ,当 ASP.NET 看到打开的 HTML 标记 () 时,它会按原样向浏览器呈现元素及其内容,并解析服务器代码表达式。

  • @:使用 运算符或 <text> 元素。 输出 @: 包含纯文本或不匹配 HTML 标记的单行内容; <text> 元素将多行括起来要输出。 当你不想将 HTML 元素呈现为输出的一部分时,这些选项非常有用。

    @if(IsPost) {
        // Plain text followed by an unmatched HTML tag and server code.
        @: The time is: <br /> @DateTime.Now
        <br/>
        // Server code and then plain text, matched tags, and more text.
        @DateTime.Now @:is the <em>current</em> time.
    }
    

    如果要输出多行文本或不匹配的 HTML 标记,可以在每行前面加上 @:,也可以将行括在元素中 <text> 。 与 运算符一 @: 样,<text> ASP.NET 使用标记来标识文本内容,并且永远不会在页面输出中呈现。

    @if(IsPost) {
        // Repeat the previous example, but use <text> tags.
        <text>
        The time is: <br /> @DateTime.Now
        <br/>
        @DateTime.Now is the <em>current</em> time.
        </text>
    }
    
    @{
        var minTemp = 75;
        <text>It is the month of @DateTime.Now.ToString("MMMM"), and
        it's a <em>great</em> day! <br /><p>You can go swimming if it's at
        least @minTemp degrees. </p></text>
    }
    

    第一个示例重复上一个示例,但使用一对 <text> 标记来包围要呈现的文本。 第二个示例中, <text></text> 标记包含三行,所有这些行都有一些未包含的文本和不匹配的 HTML 标记 (<br />) ,以及服务器代码和匹配的 HTML 标记。 同样,还可以在每行前面单独使用 @: 运算符;任一方式都有效。

    注意

    如本部分所示输出文本时(使用 HTML 元素、 @: 运算符或 <text> 元素),ASP.NET 不会对输出进行 HTML 编码。 (如前所述,ASP.NET 对前面的 @服务器代码表达式和服务器代码块的输出进行编码,本节中提到的特殊情况除外。)

空格

语句 (和字符串文本) 外部的额外空格不会影响语句:

@{ var lastName =    "Smith"; }

语句中的换行符对 语句没有影响,你可以换行语句以便于可读。 下列语句相同:

@{ var theName =
"Smith"; }

@{
    var
    personName
    =
    "Smith"
    ;
}

但是,不能在字符串文本中间换行。 以下示例无法工作:

@{ var test = "This is a long
    string"; }  // Does not work!

若要组合包装到多个行的长字符串(如上述代码),有两个选项。 可以使用串联运算符 (+) ,本文稍后将介绍。 还可以使用 @ 字符创建逐字字符串文本,如本文前面所述。 可以跨行中断逐字字符串文本:

@{ var longString = @"This is a
    long
    string";
}

代码 (和标记) 注释

批注允许你为自己或他人留下笔记。 它们还允许禁用 (注释掉) 不想运行但暂时保留在页面中的代码或标记部分。

Razor 代码和 HTML 标记有不同的注释语法。 与所有 Razor 代码一样,在将页面发送到浏览器之前, (处理 Razor 注释,然后在服务器上删除) 。 因此,Razor 注释语法允许将注释放入代码中, (甚至标记) ,你可以在编辑文件时看到,但用户看不到,即使在页面源中也是如此。

对于 ASP.NET Razor 注释,请使用 开头的批注 @* ,以 结尾 *@。 注释可以位于一行或多行上:

@*  A one-line code comment. *@

@*
    This is a multiline code comment.
    It can continue for any number of lines.
*@

下面是代码块中的注释:

@{
    @* This is a comment. *@
    var theVar = 17;
}

下面是相同的代码块,其中注释掉了代码行,这样它就不会运行:

@{
    @* This is a comment. *@
    @* var theVar = 17;  *@
}

在代码块内,作为使用 Razor 注释语法的替代方法,可以使用所用编程语言的注释语法,例如 C#:

@{
    // This is a comment.
    var myVar = 17;
    /* This is a multi-line comment
    that uses C# commenting syntax. */
}

在 C# 中,单行注释前面是 // 字符,多行注释以 /* 开头,以 */结尾。 (与 Razor 注释一样,C# 注释不会呈现到 browser.)

对于标记,你可能知道,可以创建 HTML 注释:

<!-- This is a comment.  -->

HTML 注释以字符开头 <!-- ,以 -->结尾。 不仅可以使用 HTML 注释来包围文本,还可以包围可能想要保留在页面中但不想呈现的任何 HTML 标记。 此 HTML 注释将隐藏标记的全部内容及其包含的文本:

<!-- <p>This is my paragraph.</p>  -->

与 Razor 注释不同, HTML 注释呈现 到页面,用户可以通过查看页面源来查看它们。

Razor 对 C# 的嵌套块有限制。 有关详细信息,请参阅 命名 C# 变量和嵌套块生成中断的代码

变量

变量是用于存储数据的命名对象。 可以为变量命名任何内容,但名称必须以字母字符开头,并且不能包含空格或保留字符。

变量和数据类型

变量可以具有特定的数据类型,指示变量中存储的数据类型。 可以有存储字符串值的字符串变量 (“Hello world”) 、存储整数值 ((如 3 或 79) )的整数变量,以及以各种格式存储日期值的日期变量 ((如 4/12/2012 或 2009 年 3 月) )。 还可以使用许多其他数据类型。

但是,通常不必为变量指定类型。 大多数情况下,ASP.NET 可以根据变量中的数据的使用方式来确定类型。 (有时必须指定类型;你将看到示例,其中为 true.)

如果不想指定类型) 或使用类型的名称,请使用 关键字 (keyword) (声明变量var

@{
    // Assigning a string to a variable.
    var greeting = "Welcome!";

    // Assigning a number to a variable.
    var theCount = 3;

    // Assigning an expression to a variable.
    var monthlyTotal = theCount + 5;

    // Assigning a date value to a variable.
    var today = DateTime.Today;

    // Assigning the current page's URL to a variable.
    var myPath = this.Request.Url;

    // Declaring variables using explicit data types.
    string name = "Joe";
    int count = 5;
    DateTime tomorrow = DateTime.Now.AddDays(1);
}

以下示例演示了网页中变量的一些典型用法:

@{
    // Embedding the value of a variable into HTML markup.
    <p>@greeting, friends!</p>

    // Using variables as part of an inline expression.
    <p>The predicted annual total is: @( monthlyTotal * 12)</p>

    // Displaying the page URL with a variable.
    <p>The URL to this page is: @myPath</p>
}

如果将前面的示例合并到页面中,则会在浏览器中看到此内容:

Razor-Img9

转换和测试数据类型

虽然 ASP.NET 通常可以自动确定数据类型,但有时不能。 因此,可能需要通过执行显式转换来帮助 ASP.NET。 即使无需转换类型,有时测试以查看可能正在使用的数据类型也很有帮助。

最常见的情况是,必须将字符串转换为另一种类型,例如整数或日期。 以下示例演示了一个典型情况,即必须将字符串转换为数字。

@{
    var total = 0;

    if(IsPost) {
        // Retrieve the numbers that the user entered.
        var num1 = Request["text1"];
        var num2 = Request["text2"];
        // Convert the entered strings into integers numbers and add.
        total = num1.AsInt() + num2.AsInt();
    }
}

通常,用户输入以字符串的形式出现。 即使你已提示用户输入数字,即使他们输入了数字,提交用户输入并读取代码时,数据也是字符串格式的。 因此,必须将字符串转换为数字。 在此示例中,如果尝试在不转换值的情况下对值执行算术,则会导致以下错误,因为 ASP.NET 无法添加两个字符串:

无法隐式将类型“string”转换为“int”。

若要将值转换为整数,请调用 AsInt 方法。 如果转换成功,则可以添加数字。

下表列出了变量的一些常见转换和测试方法。

方法

说明

示例


AsInt(), IsInt()

将表示整数 ((如“593”) )的字符串转换为整数。

var myIntNumber = 0;
var myStringNum = "539";
if(myStringNum.IsInt()==true){
    myIntNumber = myStringNum.AsInt();
}

AsBool(), IsBool()

将“true”或“false”等字符串转换为布尔类型。

var myStringBool = "True";
var myVar = myStringBool.AsBool();

AsFloat(), IsFloat()

将具有十进制值(如“1.3”或“7.439”)的字符串转换为浮点数。

var myStringFloat = "41.432895";
var myFloatNum = myStringFloat.AsFloat();

AsDecimal(), IsDecimal()

将具有十进制值(如“1.3”或“7.439”)的字符串转换为十进制数。 (在 ASP.NET 中,小数比浮点数更精确。)

var myStringDec = "10317.425";
var myDecNum = myStringDec.AsDecimal();

AsDateTime(), IsDateTime()

将表示日期和时间值的字符串转换为 ASP.NET DateTime 类型。

var myDateString = "12/27/2012";
var newDate = myDateString.AsDateTime();

ToString()

将任何其他数据类型转换为字符串。

int num1 = 17;
int num2 = 76;
// myString is set to 1776
string myString = num1.ToString() +
  num2.ToString();

运算符

运算符是一个关键字 (keyword) 或字符,用于指示 ASP.NET 在表达式中执行哪种类型的命令。 C# 语言 (和基于它的 Razor 语法) 支持许多运算符,但你只需要识别几个运算符即可开始。 下表汇总了最常见的运算符。

“运算符”

说明

示例


+ - * /

数值表达式中使用的数学运算符。

@(5 + 13)
@{ var netWorth = 150000; }
@{ var newTotal = netWorth * 2; }
@(newTotal / 2)

=

赋值。 将语句右侧的值分配给左侧的 对象。

var age = 17;

==

相等。 true如果值相等,则返回 。 (请注意运算符和 == operator 之间的区别=。)

var myNum = 15;
if (myNum == 15) {
    // Do something.
}

!=

不相等。 true如果值不相等,则返回 。

var theNum = 13;
if (theNum != 15) {
    // Do something.
}

< > <= >=

小于、大于、小于或等于和大于或等于。

if (2 < 3) {
    // Do something.
}
var currentCount = 12;
if(currentCount >= 12) {
    // Do something.
}

+

串联,用于联接字符串。 ASP.NET 根据表达式的数据类型知道此运算符与加法运算符之间的差异。

// The displayed result is "abcdef".
@("abc" + "def")

+= -=

递增运算符和递减运算符,分别从变量) 加减 1 (。

int theCount = 0;
theCount += 1; // Adds 1 to count

.

点。 用于区分对象及其属性和方法。

var myUrl = Request.Url;
var count = Request["Count"].AsInt();

()

括号。 用于对表达式进行分组,并将参数传递给方法。

@(3 + 7)
@Request.MapPath(Request.FilePath);

[]

括号。 用于访问数组或集合中的值。

var income = Request["AnnualIncome"];

!

非。 将 true 值反转为 false ,反之亦然。 通常用作测试 false (的速记方法,即,对于非 true) 。

bool taskCompleted = false;
// Processing.
if(!taskCompleted) {
    // Continue processing
}

&& ||

逻辑 AND 和 OR,用于将条件链接在一起。

bool myTaskCompleted = false;
int totalCount = 0;
// Processing.
if(!myTaskCompleted && totalCount < 12) {
    // Continue processing.
}

在代码中使用文件和文件夹路径

你通常会在代码中使用文件和文件夹路径。 下面是可能显示在开发计算机上的网站的物理文件夹结构示例:

C:\WebSites\MyWebSite default.cshtml datafile.txt \images Logo.jpg \styles Styles.css

下面是有关 URL 和路径的一些基本详细信息:

  • URL 以) (http://www.example.com 域名或服务器名称 (http://localhost开头, http://mycomputer) 。
  • URL 对应于主计算机上的物理路径。 例如, http://myserver 可能对应于服务器上的文件夹 C:\websites\mywebsite
  • 虚拟路径是简写,用于表示代码中的路径,而无需指定完整路径。 它包括域或服务器名称后面的 URL 部分。 使用虚拟路径时,可以将代码移到其他域或服务器,而无需更新路径。

以下示例可帮助你了解差异:

完整 URL http://mycompanyserver/humanresources/CompanyPolicy.htm
服务器名称 mycompanyserver
虚拟路径 /humanresources/CompanyPolicy.htm
物理路径 C:\mywebsites\humanresources\CompanyPolicy.htm

虚拟根为 /,就像 C: 驱动器的根目录一样。 (虚拟文件夹路径始终使用正斜杠。) 文件夹的虚拟路径不必与物理文件夹同名;它可以是别名。 (在生产服务器上,虚拟路径很少与确切的物理路径匹配。)

在代码中处理文件和文件夹时,有时需要引用物理路径,有时需要引用虚拟路径,具体取决于使用的对象。 ASP.NET 提供了用于在代码中使用文件和文件夹路径的这些工具: Server.MapPath 方法、 ~ 运算符和 Href 方法。

将虚拟路径转换为物理路径:Server.MapPath 方法

方法 Server.MapPath/default.cshtml) 等虚拟路径 (转换为 C:\WebSites\MyWebSiteFolder\default.cshtml) 等 (绝对物理路径。 每当需要完整的物理路径时,都可使用此方法。 一个典型的示例是在 Web 服务器上读取或写入文本文件或图像文件时。

通常不知道托管站点服务器上的站点的绝对物理路径,因此此方法可以将已知路径(虚拟路径)转换为服务器上的相应路径。 将文件或文件夹的虚拟路径传递给 方法,并返回物理路径:

@{
    var dataFilePath = "~/dataFile.txt";
}
<!-- Displays a physical path C:\Websites\MyWebSite\datafile.txt  -->
<p>@Server.MapPath(dataFilePath)</p>

引用虚拟根:~ 运算符和 Href 方法

.cshtml.vbhtml 文件中,可以使用 运算符引用虚拟根路径 ~ 。 这非常方便,因为你可以在网站中移动页面,并且它们包含到其他页面的任何链接都不会中断。 如果你将网站移动到其他位置,它也很方便。 下面是一些示例:

@{
    var myImagesFolder = "~/images";
    var myStyleSheet = "~/styles/StyleSheet.css";
}

如果网站为 http://myserver/myapp,则 ASP.NET 在页面运行时如何处理这些路径:

  • myImagesFolder: http://myserver/myapp/images
  • myStyleSheet : http://myserver/myapp/styles/Stylesheet.css

(实际上不会将这些路径视为变量的值,但 ASP.NET 会将路径视为它们。)

可以在 ~ 上述) 和标记的服务器代码 (中使用 运算符,如下所示:

<!-- Examples of using the ~ operator in markup in ASP.NET Web Pages -->

<a href="~/Default">Home</a>
<img src="~/images/MyImages.png" />

在标记中,使用 ~ 运算符创建资源(如图像文件、其他网页和 CSS 文件)的路径。 页面运行时,ASP.NET 浏览 (代码和标记) 的页面,并解析对相应路径的所有 ~ 引用。

条件逻辑和循环

ASP.NET 服务器代码允许你根据条件执行任务,并编写代码以特定次数重复语句, (即运行循环的代码) 。

测试条件

若要测试简单条件, if 请使用 语句,该语句根据指定的测试返回 true 或 false:

@{
  var showToday = true;
  if(showToday)
  {
    @DateTime.Today;
  }
}

关键字 (keyword) if 启动块。 实际测试 (条件) 在括号中,返回 true 或 false。 如果测试为 true,则运行的语句括在大括号中。 语句 if 可以包含一个 else 块,该块指定要在条件为 false 时运行的语句:

@{
  var showToday = false;
  if(showToday)
  {
    @DateTime.Today;
  }
  else
  {
    <text>Sorry!</text>
  }
}

可以使用 块添加多个条件 else if

@{
    var theBalance = 4.99;
    if(theBalance == 0)
    {
        <p>You have a zero balance.</p>
    }
    else if (theBalance  > 0 && theBalance <= 5)
    {
        <p>Your balance of $@theBalance is very low.</p>
    }
    else
    {
        <p>Your balance is: $@theBalance</p>
    }
}

在此示例中,如果 if 块中的第一个条件不为 true,则 else if 检查条件。 如果满足该条件,则执行 块中的 else if 语句。 如果不满足任何条件,则执行 块中的 else 语句。 可以添加任意数目的 else if 块,然后使用 块作为“其他所有内容”条件关闭 else

若要测试大量条件,请使用 switch 块:

@{
    var weekday = "Wednesday";
    var greeting = "";

    switch(weekday)
    {
        case "Monday":
            greeting = "Ok, it's a marvelous Monday";
            break;
        case "Tuesday":
            greeting = "It's a tremendous Tuesday";
            break;
        case "Wednesday":
            greeting = "Wild Wednesday is here!";
            break;
        default:
            greeting = "It's some other day, oh well.";
            break;
    }

    <p>Since it is @weekday, the message for today is: @greeting</p>
}

要测试的值在示例中 (括号中, weekday 变量) 。 每个单独测试都使用以 case 冒号 (:) 结尾的语句。 如果 语句的值 case 与测试值匹配,则执行该示例中的代码块。 使用 语句 break 关闭每个 case 语句。 (如果忘记在每个 case 块中包含 break,则下一 case 个语句中的代码也将运行。) 块 switch 通常有一个 default 语句作为“其他所有内容”选项的最后一个用例,如果其他任何情况都不正确,则运行该选项。

浏览器中显示的最后两个条件块的结果:

Razor-Img10

循环代码

通常需要重复运行相同的语句。 可以通过循环来执行此操作。 例如,通常对数据集合中的每个项运行相同的语句。 如果确切地知道要循环多少次,则可以使用 for 循环。 这种循环对于计数或倒计时特别有用:

@for(var i = 10; i < 21; i++)
{
    <p>Line #: @i</p>
}

循环以for关键字 (keyword) 开头,后跟括号中的三个 语句,每个语句以分号结尾。

  • 在括号内,第一个语句 (var i=10;) 创建计数器并将其初始化为 10。 无需为计数器 i 命名 ,可以使用任何变量。 for循环运行时,计数器会自动递增。
  • 第二个语句 (i < 21;) 设置要计数的距离的条件。 在这种情况下,你希望它最多达到 20 (即,在计数器小于 21) 时继续运行。
  • (i++ ) 的第三个语句使用增量运算符,该运算符仅指定每次运行循环时,计数器应添加 1。

大括号内是将为循环的每次迭代运行的代码。 标记每次) 创建一个新的段落 (<p> 元素,并向输出添加一行,显示计数器) (的值 i 。 运行此页面时,该示例创建 11 行显示输出,每行中的文本指示项编号。

Razor-Img11

如果使用的是集合或数组,通常使用 foreach 循环。 集合是一组类似的对象, foreach 循环允许对集合中的每个项执行任务。 这种类型的循环对于集合来说很方便,因为与循环不同 for ,你不必递增计数器或设置限制。 相反, foreach 循环代码只是继续执行集合,直到它完成。

例如,以下代码返回 集合中的 Request.ServerVariables 项,该集合是一个包含有关 Web 服务器的信息的对象。 它使用 foreac h 循环通过在 HTML 项目符号列表中创建新 <li> 元素来显示每个项的名称。

<ul>
@foreach (var myItem in Request.ServerVariables)
{
    <li>@myItem</li>
}
</ul>

foreach 关键字 (keyword) 后跟括号,其中声明了一个代表示例中集合 (单个项的变量, var item) 后跟in关键字 (keyword) ,后跟要循环访问的集合。 在循环的正文中 foreach ,可以使用前面声明的 变量访问当前项。

Razor-Img12

若要创建更通用的循环,请使用 while 语句:

@{
    var countNum = 0;
    while (countNum < 50)
    {
        countNum += 1;
        <p>Line #@countNum: </p>
    }
}

while循环以关键字 (keyword) 开头while,后跟括号,可在其中指定循环在此处 (持续多长时间(只要 countNum 小于 50) ),然后是要重复的块。 循环通常递增 (添加到) 或递减, (从用于计数的变量或对象) 减去。 在此示例中,每次运行循环时, += 运算符都会将 1 添加到 countNum 。 (若要在倒计时的循环中递减变量,请使用递减运算符 -=) 。

对象和集合

ASP.NET 网站中几乎所有内容都是一个对象,包括网页本身。 本部分讨论在代码中经常使用的某些重要对象。

Page 对象

ASP.NET 中最基本的对象是 页面。 可以直接访问页面对象的属性,而无需任何符合条件的对象。 以下代码使用 Request 页面的 对象获取页面的文件路径:

@{
    var path = Request.FilePath;
}

若要明确引用当前页对象上的属性和方法,可以选择使用 关键字 (keyword) this 在代码中表示页面对象。 下面是前面的代码示例,添加了 this 以表示页面:

@{
    var path = this.Request.FilePath;
}

可以使用 对象的属性 Page 来获取大量信息,例如:

  • Request. 如你所见,这是有关当前请求的信息集合,包括发出请求的浏览器类型、页面的 URL、用户标识等。

  • Response. 这是有关响应 (页) 的信息集合,将在服务器代码运行完成后发送到浏览器。 例如,可以使用此属性将信息写入响应。

    @{
        // Access the page's Request object to retrieve the Url.
        var pageUrl = this.Request.Url;
    }
    <a href="@pageUrl">My page</a>
    

集合对象 (数组和字典)

集合是同一类型的一组对象,例如数据库中的 Customer 对象的集合。 ASP.NET 包含许多内置集合,如 Request.Files 集合。

你通常会处理集合中的数据。 两种常见的集合类型是 数组字典。 如果要存储类似项的集合,但又不想创建单独的变量来保存每个项,数组非常有用:

@* Array block 1: Declaring a new array using braces. *@
@{
    <h3>Team Members</h3>
    string[] teamMembers = {"Matt", "Joanne", "Robert", "Nancy"};
    foreach (var person in teamMembers)
    {
        <p>@person</p>
    }
}

使用数组,可以声明特定的数据类型,例如 stringintDateTime。 若要指示变量可以包含数组,请将括号添加到声明 (,例如 string[]int[]) 。 可以使用数组中项的位置 (索引) 或使用 语句来访问项 foreach 。 数组索引是从零开始的,也就是说,第一项位于位置 0,第二项位于位置 1,依此而行。

@{
    string[] teamMembers = {"Matt", "Joanne", "Robert", "Nancy"};
    <p>The number of names in the teamMembers array: @teamMembers.Length </p>
    <p>Robert is now in position: @Array.IndexOf(teamMembers, "Robert")</p>
    <p>The array item at position 2 (zero-based) is @teamMembers[2]</p>
    <h3>Current order of team members in the list</h3>
    foreach (var name in teamMembers)
    {
        <p>@name</p>
    }
    <h3>Reversed order of team members in the list</h3>
    Array.Reverse(teamMembers);
    foreach (var reversedItem in teamMembers)
    {
        <p>@reversedItem</p>
    }
}

可以通过获取 Length 数组的 属性来确定数组中的项数。 若要获取特定项在数组中的位置, (搜索数组) ,请使用 Array.IndexOf 方法。 还可以执行以下操作: (方法) Array.Reverse 或 (方法) 对内容 Array.Sort 进行排序等操作。

浏览器中显示的字符串数组代码的输出:

Razor-Img13

字典是键/值对的集合,可在其中提供键 (或名称) 来设置或检索相应的值:

@{
    var myScores = new Dictionary<string, int>();
    myScores.Add("test1", 71);
    myScores.Add("test2", 82);
    myScores.Add("test3", 100);
    myScores.Add("test4", 59);
}
<p>My score on test 3 is: @myScores["test3"]%</p>
@{myScores["test4"] = 79;}
<p>My corrected score on test 4 is: @myScores["test4"]%</p>

若要创建字典,请使用 new 关键字 (keyword) 来指示要创建新的字典对象。 可以使用 关键字 (keyword) 将字典分配给变量var。 使用尖括号 ( < > ) 指示字典中项的数据类型。 在声明的末尾,必须添加一对括号,因为这实际上是一种创建新字典的方法。

若要将项添加到字典中,可以调用 Add 字典变量的 方法 (myScores 在本例中) ,然后指定键和值。 或者,可以使用方括号来指示键并执行简单的赋值,如以下示例所示:

myScores["test4"] = 79;

若要从字典中获取值,请在括号中指定键:

var testScoreThree = myScores["test3"];

使用参数调用方法

如本文前面所述,使用编程的对象可以具有 方法。 例如, Database 对象可能具有 Database.Connect 方法。 许多方法还具有一个或多个参数。 参数是传递给方法的值,使方法能够完成其任务。 例如,查看 方法的 Request.MapPath 声明,该方法采用三个参数:

public string MapPath(string virtualPath, string baseVirtualDir, 
    bool allowCrossAppMapping);

(行已换行,使其更易于阅读。请记住,除了用引号括起来的字符串内,几乎可以放置换行符。)

此方法返回服务器上与指定的虚拟路径对应的物理路径。 方法的三个参数是 virtualPathbaseVirtualDirallowCrossAppMapping。 (请注意,在声明中,参数会列出它们将接受的数据的数据类型。) 调用此方法时,必须为所有三个参数提供值。

Razor 语法提供了两个用于将参数传递给方法的选项: 位置参数命名参数。 若要使用位置参数调用方法,请按方法声明中指定的严格顺序传递参数。 (通常可以通过阅读方法的文档来了解此顺序。) 必须遵循顺序,并且不能跳过任何参数 - 如有必要,请将空字符串传递给 ("") 或 null 没有值的位置参数。

以下示例假定网站上有一个名为 scripts 的文件夹。 代码调用 方法, Request.MapPath 并按正确的顺序传递三个参数的值。 然后,它显示生成的映射路径。

@{
    // Pass parameters to a method using positional parameters.
    var myPathPositional = Request.MapPath("/scripts", "/", true);
}
<p>@myPathPositional</p>

当一个方法具有多个参数时,可以使用命名参数使代码更具可读性。 若要使用命名参数调用方法,请指定参数名称后跟冒号 (:) ,然后指定值。 命名参数的优点是可以按所需的任何顺序传递它们。 (一个缺点是方法调用不如 compact.)

以下示例调用上述方法,但使用命名参数提供值:

@{
    // Pass parameters to a method using named parameters.
    var myPathNamed = Request.MapPath(baseVirtualDir: "/", 
        allowCrossAppMapping: true, virtualPath: "/scripts");
}
<p>@myPathNamed</p>

如你所看到的,参数按不同的顺序传递。 但是,如果运行前面的示例和此示例,它们将返回相同的值。

处理错误

Try-Catch 语句

代码中通常会有语句,这些语句可能因不受控制的原因而失败。 例如:

  • 如果代码尝试创建或访问文件,则可能会发生各种错误。 所需的文件可能不存在,它可能已被锁定,代码可能没有权限,等等。
  • 同样,如果代码尝试更新数据库中的记录,可能存在权限问题、与数据库的连接可能断开、要保存的数据可能无效等。

在编程术语中,这些情况称为 异常。 如果代码遇到异常,则会生成 (引发) 错误消息,充其量会让用户恼火:

Razor-Img14

在代码可能遇到异常的情况下,为了避免此类型的错误消息,可以使用 try/catch 语句。 在 语句中 try ,运行要检查的代码。 在一个或多个 catch 语句中,可以查找特定错误 (可能发生的特定类型的异常) 。 可以根据需要包含任意数量的 catch 语句来查找预期的错误。

注意

建议避免在 try/catch 语句中使用 Response.Redirect 方法,因为它可能会导致页面中出现异常。

以下示例显示了一个页面,该页面在第一个请求中创建一个文本文件,然后显示一个允许用户打开该文件的按钮。 该示例故意使用错误的文件名,以便导致异常。 该代码包含 catch 两个可能异常的语句: FileNotFoundException(在文件名错误时发生)和 DirectoryNotFoundException(在 ASP.NET 甚至找不到文件夹时发生)。 (可以取消注释示例中的语句,以查看当一切正常时它的运行方式。)

如果代码未处理异常,则会看到类似于上一个屏幕截图的错误页。 但是, try/catch 部分有助于防止用户看到这些类型的错误。

@{
    var dataFilePath = "~/dataFile.txt";
    var fileContents = "";
    var physicalPath = Server.MapPath(dataFilePath);
    var userMessage = "Hello world, the time is " + DateTime.Now;
    var userErrMsg = "";
    var errMsg = "";

    if(IsPost)
    {
        // When the user clicks the "Open File" button and posts
        // the page, try to open the created file for reading.
        try {
            // This code fails because of faulty path to the file.
            fileContents = File.ReadAllText(@"c:\batafile.txt");

            // This code works. To eliminate error on page,
            // comment the above line of code and uncomment this one.
            //fileContents = File.ReadAllText(physicalPath);
        }
        catch (FileNotFoundException ex) {
            // You can use the exception object for debugging, logging, etc.
            errMsg = ex.Message;
            // Create a friendly error message for users.
            userErrMsg = "A file could not be opened, please contact "
                + "your system administrator.";
        }
        catch (DirectoryNotFoundException ex) {
            // Similar to previous exception.
            errMsg = ex.Message;
            userErrMsg = "A directory was not found, please contact "
                + "your system administrator.";
        }
    }
    else
    {
        // The first time the page is requested, create the text file.
        File.WriteAllText(physicalPath, userMessage);
    }
}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Try-Catch Statements</title>
    </head>
    <body>
    <form method="POST" action="" >
      <input type="Submit" name="Submit" value="Open File"/>
    </form>

    <p>@fileContents</p>
    <p>@userErrMsg</p>

    </body>
</html>

其他资源

使用 Visual Basic 编程

附录:Visual Basic 语言和语法

参考文档

ASP.NET

C# 语言