Razor 是MVC框架视图引擎 的名称。视图引擎负责处理ASP.NET内容,并查找有关指令,将动态内容插入到发送给浏览器的输出。
视图的目标 :将模型的一个或多个部分表现给用户。意味着,视图会产生显示数据的HTML,这些数据来自于视图所接收的一个或多个对象。
准备项目 打开VS,创建ASP.NET Web应用程序 ,项目名称为Razor ,选择MVC空模板。
定义模型 在Models文件夹添加Product 类。
public class Product { public int ProductID { get ; set ; } public string Name { get ; set ; } public string Description { get ; set ; } public decimal Price { get ; set ; } public string Category { get ; set ; } }
定义控制器 添加HomeController 。定义Index 动作方法,并把Product对象传递给View。
public class HomeController : Controller { Product myProduct = new Product { ProductID = 1 , Name = "Kayak" , Description = "A boat for one person" , Category = "Watersports" , Price = 275 M }; public ActionResult Index ( ) { return View(myProduct); } }
创建视图 添加Index视图,模板设置为空,选择Product模型类。
使用模型对象 Razor语句 以@字符 开始。@model语句 声明了通过动作方法传递给该视图 模型对象的类型,我们可以通过@Model 来引用视图模型对象的方法 、字段 和属性 。
@model Razor.Models.Product @{ Layout = null; } <!DOCTYPE html> <html > <head > <meta name ="viewport" content ="width=device-width" /> <title > Index</title > </head > <body > <div > @Model.Name </div > </body > </html >
使用布局 @{ … } 是Razor代码块 ,这种代码块允许在视图中包含C# 语句。
在MVC应用程序中,Razor视图会被编译成C#类,而所用的基类定义了Layout属性。
Layout属性 的值设置为null ,代表该视图是自包含 的,并且会渲染客户端所需要的全部 内容。
创建布局 右键Views文件夹 ,添加新建项 ,选择MVC5 布局页 ,文件名设置为_BasicLayout.cshtml 。
<!DOCTYPE html> <html > <head > <meta name ="viewport" content ="width=device-width" /> <title > @ViewBag.Title</title > </head > <body > <h1 > Product Information</h1 > <div style ="padding: 20px; border: solid medium black; font-size: 20pt;" > @RenderBody() </div > <h2 > Visit <a href ="http://apress.com" > Apress</a > </h2 > </body > </html >
注意 :
@RenderBody方法 的调用会将动作方法所指定的视图内容 插入到布局标记 之中。
ViewBag.Title 会查找Title属性,目的是设置title元素的内容 。
代码添加了两个标题元素(h1和h2),以及对div元素运用了一些css样式,目的是让来自布局 的内容与来自视图 的内容有所区别。
运用布局 为了将布局运用于视图,只需要设置视图的Layout属性 的值即可。
布局中包含了一些HTML元素,定义了HTML页面的结构 。
在Index视图中使用Layout属性。
@model Razor.Models.Product @{ ViewBag.Title = "Product Name" ; Layout = "~/Views/_BasicLayout.cshtml" ; } Product Name: @Model.Name
视图起始文件 如果有多个视图 ,则必须在每一 视图都要指定布局文件 ,这是难以维护的。
视图起始文件 :在渲染一个视图时,MVC框架会查找一个叫做_ViewStart.cshtml 的文件。框架会将此文件的内容视为视图文件的一部分 。
在Views文件夹添加MVC5 布局页 ,名称设置为_ViewStart.cshtml 。
@{ Layout = "~/Views/_BasicLayout.cshtml" ; }
这样就可以在Index视图中去掉Layout属性。
@model Razor.Models.Product @{ ViewBag.Title = "Product Name" ; } Product Name: @Model.Name
注意 :
如果添加了视图起始文件_ViewStart.cshtml ,则MVC会对此文件进行定位且自动使用其内容(所有视图默认使用视图起始文件的布局) 。
如果在视图中重新定义了Layout 的值,则会覆盖 视图起始文件中所指定的布局。(Layout优先级:视图 > 视图起始文件)
Layout 属性设置为null ,与不使用Layout 属性是不同的。
共享布局 在HomeController 中添加NameAndPrice 动作方法。
public ActionResult NameAndPrice ( ) { return View(myProduct); }
添加NameAndPrice 视图,选择Product模型类,勾选使用布局页 ,选择_BasicLayout.cshtml 。(这里如果不勾选布局页,也是同样的结果,因为视图起始文件引用了相同的布局)
@model Razor.Models.Product @{ ViewBag.Title = "NameAndPrice" ; Layout = "~/Views/_BasicLayout.cshtml" ; } <h2>NameAndPrice</h2> The product name is @Model.Name and it costs $@Model.Price
Razor表达式 动作方法与视图所起的作用。
组件
要做的事
不做的事
动作方法
向视图传递 一个视图模型
向视图传递格式化的数据
视图
用视图模型对象向用户表现内容
修改 视图模型对象的任何方面
当然可以在动作方法中创建要显示的字符串 ,并把它作为视图模型 传递给视图,但这破坏了MVC模式 的好处。
插入数据值 用Razor表达式 能做的最简单的事情,是将数据值插入到标记中 ,可以用@Model 表达式来做这件事,以引用视图模型对象所定义的属性与方法。或使用@ViewBag 表达式引用动态属性。
在HomeController添加DemoExpressions 动作方法。
public ActionResult DemoExpressions ( ) { ViewBag.ProductCount = 1 ; ViewBag.ExpressShip = true ; ViewBag.ApplyDiscount = false ; ViewBag.Supplier = null ; return View(myProduct); }
创建DemoExpressions 视图,选择Product模型类。视图使用Razor表达式 显示数据,这些数据是动作方法传递给视图的。
@model Razor.Models.Product @{ ViewBag.Title = "DemoExpression"; } <table > <thead > <tr > <th > Property</th > <th > Value</th > </tr > </thead > <tbody > <tr > <td > Name</td > <td > @Model.Name</td > </tr > <tr > <td > Price</td > <td > @Model.Price</td > </tr > <tr > <td > Stock Level</td > <td > @ViewBag.ProductCount</td > </tr > </tbody > </table >
设置标签属性的值 可以通过Razor表达式 ,设置元素的标签属性 的值。
修改DemoExpression视图,在视图中使用Razor表达式设置标签属性值 。
@model Razor.Models.Product @{ ViewBag.Title = "DemoExpression"; } <table > <thead > <tr > <th > Property</th > <th > Value</th > </tr > </thead > <tbody > <tr > <td > Name</td > <td > @Model.Name</td > </tr > <tr > <td > Price</td > <td > @Model.Price</td > </tr > <tr > <td > Stock Level</td > <td > @ViewBag.ProductCount</td > </tr > </tbody > </table > <div data-discount ="@ViewBag.ApplyDiscount" data-express ="@ViewBag.ExpressShip" data-supplier ="@ViewBag.Supplier" > The containing element has data attributes </div > Discount:<input type ="checkbox" checked ="@ViewBag.ApplyDiscount" /> Express:<input type ="checkbox" checked ="@ViewBag.ExpressShip" /> Supplier:<input type ="checkbox" checked ="@ViewBag.Supplier" />
注意 :
data标签属性 ,以data-为前缀,作为创建自定义标签属性 的一种非正规方式,现已称为H5的正规标准 。
Razor会将后台的null 渲染成空字符串 。如Supplier标签属性。
Razor使用checked标签属性 时,用是否出现该标签属性 而不是它的值 来改变元素的配置。即,Razor在值为False 或null 时,会完全删除 该标签属性。如ApplyDiscount和Supplier标签属性。
使用条件语句 Razor能处理条件语句,这是Razor的核心功能。这能够创建复杂而流畅的视图,使视图仍易于阅读和维护。
修改DemoExpression视图,在视图中使用Razor条件语句 。
@model Razor.Models.Product @{ ViewBag.Title = "DemoExpression"; } <table > <thead > <tr > <th > Property</th > <th > Value</th > </tr > </thead > <tbody > <tr > <td > Name</td > <td > @Model.Name</td > </tr > <tr > <td > Price</td > <td > @Model.Price</td > </tr > <tr > <td > Stock Level</td > <td > @switch ((int)ViewBag.ProductCount) { case 0: @: Out of Stock break; case 1: <b > Low Stock (@ViewBag.ProductCount)</b > break; default: @ViewBag.ProductCount break; } </td > </tr > </tbody > </table >
注意 :
在视图中使用switch表达式 ,需要使用@switch 开头。
必须将ViewBag.ProductCount 属性的值转换成int 才能够在switch语句中使用。因为Razor中的switch表达式不能求取动态属性的值 。
如果使用@: 前缀,则Razor阻止 此行解释为一条C#语句。可以用此方法,将HTML元素中的文本插入到视图 。
修改DemoExpression视图,在视图中使用if语句 (与switch语句结果相同)。
@model Razor.Models.Product @{ ViewBag.Title = "DemoExpression"; } <table > <thead > <tr > <th > Property</th > <th > Value</th > </tr > </thead > <tbody > <tr > <td > Name</td > <td > @Model.Name</td > </tr > <tr > <td > Price</td > <td > @Model.Price</td > </tr > <tr > <td > Stock Level</td > <td > @if (ViewBag.ProductCount == 0) { @: Out of Stock } else if (ViewBag.ProductCount == 1) { <b > Low Stock (@ViewBag.ProductCount)</b > } else { @ViewBag.ProductCount } </td > </tr > </tbody > </table >
枚举数组和集合 在HomeController添加DemoArray 动作方法。该动作方法创建了Product[] 对象,并传递给View 方法。
public ActionResult DemoArray ( ) { Product[] array = { new Product { Name = "Kayak" , Price = 275 M }, new Product { Name = "Lifejacket" , Price = 48.95 M }, new Product { Name = "Soccer ball" , Price = 19.50 M }, new Product { Name = "Corner flag" , Price = 34.95 M } }; return View(array); }
VS的支架特性不能指定一个数组作为模型类 ,但Razor本身能够支持数组。
创建一个不含模型 的DemoArray 视图,手动添加@model表达式 。
@model Razor.Models.Product[] @{ ViewBag.Title = "DemoArray"; } @if (Model.Length > 0) { <table > <thead > <tr > <th > Product</th > <th > Price</th > </tr > </thead > <tbody > @foreach (Razor.Models.Product p in Model) { <tr > <td > @p.Name</td > <td > @p.Price</td > </tr > } </tbody > </table > } else { <h2 > No product data</h2 > }
处理命名空间 可以对一个视图运用@using表达式 ,以引入命名空间 ,就像在C#类那样。一个视图可以包含多个 @using表达式。
在DemoArray视图中运用@using表达式 ,并去掉 @model表达式和foreach循环中的命名空间 。
@using Razor.Models @model Product[] @{ ViewBag.Title = "DemoArray"; } @if (Model.Length > 0) { <table > <thead > <tr > <th > Product</th > <th > Price</th > </tr > </thead > <tbody > @foreach (Product p in Model) { <tr > <td > @p.Name</td > <td > @p.Price</td > </tr > } </tbody > </table > } else { <h2 > No product data</h2 > }