.net mvc笔记3_Understanding Razor Syntax

Understanding Razor Syntax

MVC3新视图引擎的名字叫做Razor。ASP.NET视图引擎处理web页面,寻找包含在服务器端指令的特殊元素。正如我们前面已经提到的,标准的ASPX视图引擎依靠<%和%>元素,这是所有ASP.NET开发人员都熟悉的。

利用Razor,MVC开发团队围绕@符号引入了一组新的语法元素。大体上,虽然有几个新规则,但如果你熟悉<% %>语法,运用Razor语法应该没有太多问题。本小节中,我们将给你提供一个快速的Razor语法教程,以使你看到它们时能够认识这个新元素。

1、Creating the Project

为了演示Razor的特性和语法,让我们生成一个MVC项目。

2、Defining the Model

我们打算用一个十分简单的域模型,它只有一个域类,名为Product。添加一个文件到你的Models文件夹,名为Product.cs,并确保内容与列表5-32匹配。

Listing 5-32. Creating a Simple Domain Model Class

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 
 6 namespace _5_32RazorSyntax.Models
 7 {
 8     public class Product
 9     {
10         public int ProductID { get; set; }
11         public string Name { get; set; }
12         public string Description { get; set; }
13         public decimal Price { get; set; }
14         public string Category { set; get; }
15     }
16 }

3、Defining the Controller

右击项目中的Controllers文件夹,选择“添加”,然后从弹出菜单选“控制器”。设置名字为ProductController,并从Template选项中选择empty controller。点击Add按钮以生成这个控制器类,然后编辑文件内容使它如列表5-33。

Listing 5-33. A Simple Controller

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using _5_32RazorSyntax.Models;  //将Product.cs的namespace包含进来
 7 
 8 namespace _5_32RazorSyntax.Controllers
 9 {
10     public class ProductController : Controller
11     {
12         public ActionResult Index()
13         {
14             Product myProduct = new Product
15             {
16                 ProductID = 1,
17                 Name = "Kayak",
18                 Description = "A boat for one person",
19                 Category = "Watersports",
20                 Price = 275M
21             };
22 
23             return View(myProduct);
24         }
25 
26     }
27 }

我们在这里的焦点是Razor,因此我们对MVC模型中的Controller部分设置得较为松散。Index行为方法(action method)创建了Product的一个实例,并传递给View方法(未使用repository)。

4、Creating the View

为了生成视图,在ProductController类的Index方法上点击鼠标右键,选择Add View。选中“create a strongly typed view”,并在下拉列表中选中类Product。

note 如果在下拉列表中没有看到Product类,则需要先把项目编译一遍,然后再重新创建视图。编译之后Visual Studio才会识别出model classes。

 选中“使用布局或母板页”复选框,但不要拾取一个文件——只让这个文本框为空。点击添加,以生成这个视图,它将以Index.cshtml出现在Views/Product文件夹中。

5、Setting the Default Route

出于方便,我们打算告诉MVC对我们应用程序的/URL(也就是根URL,首页)请求应该被引向Product控制器的Index行为方法。要完成这一步骤,打开Global.asax文件并找到RegisterRoutes方法。在这个方法中有一个对routes.MapRoute的调用。在Default中把赋给controller属性的值从默认的”Home”修改为”Product”,如列表5-34中的黑体所示。

Listing 5-34. Setting the Controller for the Default Route

1 routes.MapRoute(
2                 "Default", // Route name
3                 "{controller}/{action}/{id}", // URL with parameters
4                 new { controller = "Product", action = "Index", id = UrlParameter.Optional } // Parameter defaults
5             );

对这个路由系统先不用着急。我们将在第11章解释它如何工作。

6、Examining a Basic Razor View

Razor视图的文件扩展名为.cshtml,而以前的MVC版本和ASP.NET Web表单所使用的是.aspx。你在MVC 3项目中仍然可以用ASPX视图引擎,但我们更喜欢用Razor引擎,它对微软的MVC开发团队来说是一个强有力的重点领域。

    如果你打开Index.cshtml文件进行编辑,你将看到它的内容类似于列表5-35。这是Razor视图的起点。

Listing 5-35. A Simple Razor View

1 @model _5_32RazorSyntax.Models.Product
2 
3 @{
4     ViewBag.Title = "Index";
5 }
6 
7 <h2>Index</h2>

7、Working with the Model Object

不管它多短,列表5-35有很多事要做。让我们从视图的第一行开始:

@model _5_32RazorSyntax.Models.Product

    Razor语句以@字符开头。这里,我们用@model定义了在此定义点之后本视图中可以使用的model view。正如我们在第3章中讨论的,强类型视图让我们把模型对象(model object)传递给视图。我们可以通过@model来引用方法、字段和属性(method、field、property)。如列表5-36所示。

Listing 5-36. Referring to the Model Object

1 @model _5_32RazorSyntax.Models.Product
2 
3 @{
4     ViewBag.Title = "Index";
5 }
6 
7 <h2>Name: @Model.Name</h2>

从上面的例子你可以看到,Razor语句通常不需要结束标记(只需用@开头),除非使用代码块才需要。注意到我们在开头第一句话中指定模型的类型时,使用的是@model(m是小写)。当我们在使用中引用模型对象时,使用的是@Model(M是大写)。

8、Defining Razor Code

上面的列表5-36演示了如何调用Razor代码,如下:

<h2>Name: @Model.Name</h2>

你不仅限于只调用模型,但这是最常用的行内标签。你可以包含任何C#语句。如列表5-37所示

Listing 5-37. Calling Arbitrary Functions with Razor

1 @model _5_32RazorSyntax.Models.Product
2 
3 @{
4     ViewBag.Title = "Index";
5 }
6 
7 <h2>Name: @Model.Name</h2>
8 Time view rendered: @DateTime.Now.ToShortTimeString()

 这个调用以短字符串格式返回当前时间。用Razor调用一个函数或属性时会将调用后的结果插入到页面的Html中。在上面的例子中我们用@Model.<propertyname> 的形式进行了调用,将属性的值添加到页面中。

    Razor可以以十分相似的方式处理复杂的代码块。我们以@字符开始,然后进行C#编码,如列表5-38所示。

Listing 5-38. A More Complex Code Block

 1 @model _5_32RazorSyntax.Models.Product
 2 
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6 
 7 <h2>Name: @Model.Name</h2>
 8 
 9 @if (Model.Category == "Watersports")
10 {
11     <p>@Model.Category <b>Splash!</b></p>
12 }
13 Time view rendered: @DateTime.Now.ToShortTimeString()

在这个例子中,我们包含了一个if语句,当Product条目的Category属性是Watersports时,把附加内容插入到页面。Razor能够智能化地识别if体中的HTML标签,并把它处理为嵌入标记。它也寻找更多的@标签,处理它们并把结果放入到web页面中。

 

如果你想把文本内容包含在代码块中而又不以HTML元素开头,那你就需要给予Razor一个辅助工具,这就是@:标签,如列表5-39所示。

Listing 5-39. Content Inside a Code Block That Doesn’t Start with an HTML Element

 1 @model _5_32RazorSyntax.Models.Product
 2 
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6 
 7 <h2>Name: @Model.Name</h2>
 8 
 9 @if (Model.Category == "Watersports")
10 {
11     @:Category:@Model.Category <b>Splash!</b>  //前面要显示文本Category:,因为是在代码块中,直接显示不允许,所以加上@:
12 }
13 <p />
14 Time view rendered: @DateTime.Now.ToShortTimeString()

如果你需要包含数行文本,每一行都不用HTML元素开始,你可以用text元素,如列表5-40所示。这等同于每一行前面缀以@:元素

Listing 5-40. Using the Text Element

 1 @model _5_32RazorSyntax.Models.Product
 2 
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6 
 7 <h2>Name: @Model.Name</h2>
 8 
 9 @if (Model.Category == "Watersports")
10 {
11     <text>
12         Category: @Model.Category <b>Splash!</b>
13         <pre>
14             Row, row, row your boat,
15             Gently down the stream...
16         </pre>
17     </text>
18 }
19 <p />
20 Time view rendered: @DateTime.Now.ToShortTimeString()

在text块中你仍然可以包含Razor标记和HTML元素。这只是当有多行要处理时,比用@:更方便些。

9、Including Multiple Functions in a Code Block

你可以使用@{开头,再用大括号}结尾来将更大范围的代码和内容组合在一起,列表5-41提供了一个演示。

Listing 5-41. Creating a Larger Code Block

 1 @model _5_32RazorSyntax.Models.Product
 2 
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6 
 7 <h2>Name: @Model.Name</h2>
 8 
 9 @{
10     if (Model.Category == "Watersports")
11     {
12         @:Category: @Model.Category <b>Splash!</b>
13     }
14     if (Model.Price > 10)
15     {
16         <h5>Pricey!</h5>
17     }
18 }

这里有两个if块,相互进行独立的操作。

通过@{...}来构成代码块的方法更多的用在给变量赋值。就像上面这个例子中的ViewBag.Title = "Index";一样,我们可以很容易地添加更多的赋值语句。

10、Passing Data Using the View Bag Feature

上一章我们看到了如何使用View Data特性把数据从控制器传到视图。用View Bag特性我们可以完成同样的功能。列表5-42演示了如何在Product控制器中做这件事。

Listing 5-42. Using the View Bag in the Controller

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using _5_32RazorSyntax.Models;  //将Product.cs的namespace包含进来
 7 
 8 namespace _5_32RazorSyntax.Controllers
 9 {
10     public class ProductController : Controller
11     {
12         public ActionResult Index()
13         {
14             Product myProduct = new Product
15             {
16                 ProductID = 1,
17                 Name = "Kayak",
18                 Description = "A boat for one person",
19                 Category = "Watersports",
20                 Price = 275M
21             };
22 
23             ViewBag.ProcessingTime = DateTime.Now.ToShortTimeString();
24             return View(myProduct);
25         }
26 
27     }
28 }

ViewBag是动态类型,这意味着你可以通过直接赋值来确定属性。例如上面的ProcessingTime属性在把当前时间赋值给它之前是不存在的,直到我们将当前时间赋值给它,它才建立起来。在视图中我们再用同样的格式从ViewBag中把数据读取出来。如列表5-43所示。

Listing 5-43. Using the View Bag in the View

 1 @model _5_32RazorSyntax.Models.Product
 2 
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6 
 7 <h2>Name: @Model.Name</h2>
 8 
 9 @{
10     if (Model.Category == "Watersports")
11     {
12         <text>
13             <p>Description: @Model.Description <b>(Splash!)</b></p>
14             <p>Category: @Model.Category</p>
15         </text>
16     } 
17     else
18     {
19         @:Description: @Model.Description
20     }      
21 }
22 View rendered at @ViewBag.ProcessingTime

使用ViewBag跟ViewData比起来没有明显的优势,也许会少敲几下键盘。我们提到它,是因为Visual Studio为我们创建试图时就自动使用了它,就是视图中的第一个代码块

@{

    ViewBag.Title = "Index";

}

    这个块含有一条语句,把字符串赋给一个名为Title的属性。在下一小节,我们将解释其意义。

 

11、Working with Layouts

 当我们生成视图时,我们选定我们想使用布局,但我们并没有告诉Visual Studio用哪一个。如果你仔细考察添加视图对话框,你会看到一些有用的信息

对话框告诉我们如果布局已经在_viewstart文件中设置了,那就让布局引用为空(leave the layout reference blank if it is already set in a _viewstart file)如果你查看你MVC项目中的Views文件夹,你将看到一个名为_ViewStart.cshtml的文件,其内容如列表5-46所示。

Listing 5-46. The _ViewStart.cshtml File

@{

    Layout = "~/Views/Shared/_Layout.cshtml";

}

    MVC在生成视图时会查找_ViewStart.cshtml文件,读取这个文件中的任何指令并运用它们,就好象它是包含在视图文件中一样。这里,只有一条指令,它为这个视图设置的布局是Views/Shared文件夹中的_Layout.cshtml文件。

note 名字以下划线开头的视图文件不会返回给用户,即使直接在访问它们也不会。

当我们选中了选项表示我们要使用“Use layout or master page”,却又没告诉Visual Studio我们要使用哪一个,这个时候就是让MVC自动选择_ViewStart.cshtml。当然,我们可以在视图中明确地定义一个布局,但这种方法意味着我们项目中的每个视图不能复制同样的设置。下面我们打开这个布局文件,我们可最终理解在Index视图中调用ViewBag的意义。_Layout.cshtml的内容如列表5-44所示。

Listing 5-44. The _Layout.cshtml File

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>@ViewBag.Title</title>
 5     <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
 6     <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
 7 </head>
 8 
 9 <body>
10     @RenderBody()
11 </body>
12 </html>

布局(layout)相当于ASPX的母板页(master page)。我们在Index视图设置的ViewBag.Title属性被读取,并用作为HTML的title元素的内容。相对于ASPX样式的content placeholder部分,Razor通过调用@RenderBody()来包含进视图的身体部分。与母板页十分相似,Razor布局含有HTML、脚本、以及其它你希望在视图中避免复制的元素。这里,它包括了HTML文档的基本结构,以及Index视图将被生成的内容和插入到HTML的body元素中的内容。

12、Working Without Layouts

Razor布局是可选的。如果你在生成一个视图时未选布局选项,你将获得一个类似于列表5-45所示的模板。

Listing 5-45. A View That Doesn’t Use a Layout

 1 @{
 2     Layout = null;
 3 }
 4 
 5 <!DOCTYPE html>
 6 
 7 <html>
 8 <head>
 9     <title>Index</title>
10 </head>
11 <body>
12     <div>
13         
14 
15     </div>
16 </body>
17 </html>

由于没有布局,视图必须含有生成一个HTML页面所需的全部内容,包括html、head、以及body元素。注意,这种情况下你必须明确地把Layout设置为null。如果你不这么做,视图将用_ViewStart.cshtml文件中指定的布局 — 有时经常会让你感到莫明其妙。

 

 

posted @ 2013-09-05 11:58  褐色鸟群  阅读(308)  评论(0编辑  收藏  举报