以往开发ASP.NET Web Form时,在ASPX页面上都会出现许多夹杂C#/VB.NET与HTML的情况,而先前使用<%...%>这种传统圆角括号的表示法会让HTML标签与ASP.NET代码区块混杂一起,当页面变得复杂后,这类混合的代码也开始变得难以阅读,相信大家都有相同的感受。

从ASP.NET MVC3开始引入了全新的Razor语法,用@符号来代表代码段,试图提供一个容易学习又精简的语法。Razor语法推出之后,广受ASP.NET MVC开发人员的喜爱,搭配Visual Studio开发工具的语法高亮显示下,Razor语法也让整份View页面内的HTML标签与服务器代码结合得非常漂亮,不再有吃意大利面的感觉了。

我们先来回顾以往ASP.NET Web Form在ASPX页面上输出当前时间的表示法:

  1. <%: DateTime.Now %>

若使用Razor语法,将会变成以下撰写风格

  1. @DateTime.Now

Razor并不是一个代码语言,它只是一种用在View页面的代码区块撰写风格罢了,所写的代码一样是C#或VB.NET,因此开人员并不用额外学习过多的语言就可以快速上手。

若要使用C#语言来编写Razor页面,View页面的扩展名必须使用cshtml才行。同理VB.NET语言,要用vbhtml。

1.Razor基本语法

在页面中输出单一变量时,只要在C#语句之前加上@符号即可。

  1. <p>
  2. 现在时刻:@DateTime.Now
  3. </p>

请注意,上述范例中虽然使用C#语言编写代码,但输出单一变量时不需要加上分号结尾。在页面中输出一段含有表达式的结果时,必须在前后加上一个小括号。

  1. <p>
  2. 会员名称:@(User.Identity.Name+Model.MemberLevel)
  3. 启用状态:@(ViewBag.IsEnabled?"启用":"停用")
  4. </p>

在页面中执行多行C#代码时,必须在前后加上个大括号。

  1. @{
  2. var name="Will";
  3. var message="你好,我是 "+name;
  4. }

请注意,上述范例中由于@{到}之间属于一个C#代码区段,在撰写代码时必须符合C#语言规范,也就是每句话都要有分号结尾。

如果要在多行C#代码的Razor语法中插入HTML或其他文字内容,必须在每一行最前面加上一个“@:”符号,而且加上“@:”符号的这行代码里,也可以再加上其他Razor变量。

  1. @{
  2. var name="Will";
  3. @:你好,我是@name
  4. }

如果要在Razor视图页面中标识服务器端注释,可以使用“@*”与“*@”来当注解的头尾。

  1. @*<hgroup class="title">
  2. <h1>@ViewBag.Title.</h1>
  3. <h2>@ViewBag.Message</h2>
  4. </hgroup>*@

如果要在Razor视图页面中输出"@"符号。

  1. @@Will_Huang

上述Razor语法最后会输出“@Will_Huang”。

2.Razor与HTML混合输出

在View视图里混合使用HTML标签与Razor语法,在许多情况下可以用得非常顺利,但如果不了解Razor的判断逻辑,也可能会让你在开发的过程中不断受挫,现在就来介绍几个常用的混合编写风格。

在页面中编写if判断句,其范例如下:

  1. @if (ViewBag.IsEnabled){
  2. @:启用
  3. } else {
  4. @:停用
  5. }

如果要在代码区块中输出大量文字,只要在代码区块里的前后加上一组HTML标签即可,Razor会只能地判断出这不是一段C#语法,而是一段HTML标签文字,如此一来,就不用在每一行前面加上“@:”符号了,如下所示。

  1. @if (ViewBag.IsEnabled)
  2. {
  3. <span>启用</span>
  4. } else {
  5. <span>停用</span>
  6. }

VS2012提供Razor语法的高亮显示,只要是Razor可被识别的C#代码,都会在背景加上一个淡淡的蓝色,如果是白底色的话,那就代表是Razor以外的纯文字。

如果我们在这个区段中完全不想输出任何前后的标签该怎么办呢?在Razor页面里,可以使用特殊的<text>标签来代替这个HTML标签,最后输出到浏览器时不会输出<text>这个标签,如下所示。

  1. @if (ViewBag.IsEnabled)
  2. {
  3. <text>
  4. 显示启用的HTML段落:
  5. <p>
  6. @ViewBag.EnabledMessage
  7. </p>
  8. </text>
  9. } else {
  10. <text>
  11. 显示停用的HTML段落:
  12. <p>
  13. @ViewBag.DisabledMessage
  14. </p>
  15. </text>
  16. }

3.Razor与HTML混合输出陷阱与技巧

(1)属性名称误判

有时候我们必须让HTML内容与Razor语句紧紧黏在一起。显示效果为,“您好,Will先生”,其中Will为一个变量ViewBag.Name。如果输入以下Razor语法:

  1. 您好,@ViewBag.Name先生

这句话中,Razor会把“@ViewBag.Name先生”当成一个C#语法,修改如下:

  1. 您好,@(ViewBag.Name)先生

另一种解决方法就是多用一个HTML标签包起来,如下:

  1. 您好,<span>@ViewBag.Name</span>先生

或修改如下:

  1. 您好,@ViewBag.Name<span>先生</span>

(2)未预期的额外属性

要输出如下。

  1. 类别是System.Web.Mvc.Controller

如果按以下输出,会出错。

  1. @{
  2. ViewBag.MvcNamespace="System.Web.Mvc";
  3. }
  4.  
  5. 类别是@ViewBag.MvcNamespace.Controller

如何修改?

  1. 类别是@(ViewBag.MvcNamespace).Controller

(3)输出Email地址与@转义符

如果我们要在Razor页面中输出Email超链接,输出的结果可能是这样:

  1. <a href="mailto:teacher@example.com">teacher@example.com</a>

这里并不需要改成@@,因为Razor会自动判断前后文,只要"@"的前面与后面都有文字的情况下,@就会停用Razor语法解析,所以在Razor里输入Email是完全不用编写“@”转义字符。

如果要输出的HTML格式如下:

  1. <a id="LinkBlog01" href="http://blog.miniasp.com">The will will web</a>

要将Blog01替换成Razor变量,那又应该如何输入呢?

  1. @{
  2. ViewBag.BlogID="Blog01";
  3. }
  4.  
  5. <a id="Link@View.BlogID" href="http://blog.miniasp.com">The will will web</a>

以上代码将不会被正常解析。解决方法可以加上小括号。

  1. <a id="Link@(View.BlogID)" href="http://blog.miniasp.com">The will will web</a>

(4)输出未经HtmlEncode的字符串

预设使用Razor语法输出变量,所有内容预设都会被HTML编码(HtmlEncode),这是为了保护网页不致遭受跨网站脚本攻击(Cross-Site Scripting, XSS),有了这个预设值,能保证新手开发人员不写出不安全的代码。

  1. @{
  2. ViewBag.Description="<span style='font-weight:bold;'>描述文字</span>";
  3. }
  4.  
  5. @ViewBag.Description

最后输出的结果会是HtmlEncode过的版本如下:

  1. &lt;span style=&#39;font-weight:bold;&#39;&gt;这是描述文字&lt;/span&gt;

如果我们要强迫字符串原封不动地输出,可以利用@Html.Raw辅助方法帮助我们输出内容,我们可以修改上述Razor代码,代码如下:

  1. @{
  2. ViewBag.Description="<span style='font-weight:bold;'>这是描述文字</span>";
  3. }
  4.  
  5. @Html.Raw(ViewBag.Description)

最后的输出如下:

  1. <span style='font-weight:bold;'>这是描述文字</span>

4.Razor与ASPX语法比较

5.Razor的母版页面框架

传统的ASP.NET从2.0版开始推出了MasterPage母版页面框架,让你在ASP.NET Web Form页面可以通过MasterPage组织出全站一致的外观与界面。而ASP.NET MVC 1.0/2.0也沿用MasterPage架构组织View页面的HTML版面架构,不过,ASP.NET MVC3.0推出的RazorView内建的母版页面语法与原本的WebFormView的MasterPage相差甚远,因此,你可以把Razor母版页面当成是一个全新的架构来学习,只是母版页面子观念上是差不多的。

(1)Razor页面执行顺序

当Controller回传ViewResult给MvcHandler之后,MvcHandler会先设法找出对应的视图页面,当找到适当的Razor页面后,就会进入Razor页面执行生命周期,在Razor页面的执行过程中有个固定的执行顺序。

被MvcHandler找到的Razor页面会优先执行,执行完毕后,会检查这个View页面是否含有母版页面所需的Layout属性,如果有的话便试图载入Layout属性指定的Razor母版页面,找到母版页面之后会开始将内容响应给用户端。

我们先以传统ASP.NET Web Form的MasterPage作为例子,当MasterPage执行的时候,会先找出ContentPlaceHolder控制项,并将之前母版页面的执行结果填入后输出到用户端。如下所示:

  1. <asp:ContentPlaceHoder ID="MainContent" runat="server" />

实际上在沟通的时候,会把这种在MasterPage定义一个区块的动作戏称为“挖洞”,也就是在MasterPage里挖了一个洞,然后由主要页面的内容填入。

在Razor里,当母版页面被载入后,执行的过程也一样,在Razor母版页面里也会定义出一些需要被填入的内容(挖洞),然后让主要页面的内容填入。

(2)关于_ViewStart文件

/Views/_ViewStart.cshtml文件会在/Views/目录下任何View被载入前就先被载入,也就是View视图页面在执行之前,一定会先来这里寻找有没有/Views/_ViewStart.cshtml这个文件,只要有这个文件就会先载入执行。

接着再来看看这个预设文件的内容,此文件只包含了一行指定Layout属性的代码,所代表的的意义是:所有/Views/目录下的View预设都要以~/Views/Shared/_Layout.cshtml为母版页面。

这个_ViewStart.cshtml文件不仅能出现在/Views/目录下,任何与Controller同名的Views子目录下也都能出现相同的_ViewStart.cshtml文件,如此一来,就可以让不同的Controller预设载入不同的母版页面。

(3)关于_Layout母版页面 

/Views/Shared/_Layout.cshtml文件,有两个Razor语法,分别是@RenderBody与@RenderSection这两段声明,而这就是所谓的“挖洞宣言”,如下所示。

  1. </header>
  2. <div id="body">
  3. @RenderSection("featured", required: false)
  4. <section class="content-wrapper main-content clear-fix">
  5. @RenderBody()
  6. </section>
  7. </div>

@RenderBody()在Razor母版页面中可以视为“预设坑洞”,呈现子页的主体内容,也就是主要的View页面在没有特别声明的情况下,所有内容都会被填入到@RenderBody()这个位置。

@RenderSection在Razor母版页面中可以被视为“具名坑洞”,呈现特别的节部分。以下语法为例,我们在母版页面中定义了一个名为featured的坑洞,第二个required具名参数则是声明这个坑洞是否必须被填满,如果你在母版页面设定的“具名坑洞”把required参数指定为true的话,那么所有载入这个母版页面的View页面都必须输出相对应的内容,否则就会发生例外状况。

  1. @RenderSection("featured", required:false)

在Index.cshtml页面,可以使用一个特殊的Razor语法,名为@section,且在后面必须接上一个“坑洞名称”,比如featured,而在这个@section featured声明里,对Razor来说这就是一个代码区块,所套用的Razor规则也都一样。

  1. @{
  2. ViewBag.Title = "Home Page";
  3. }
  4. @section featured {
  5. <section class="featured">
  6. <div class="content-wrapper">
  7. <hgroup class="title">
  8. <h1>@ViewBag.Title.</h1>
  9. <h2>@ViewBag.Message</h2>
  10. </hgroup>
  11. <p>
  12. To learn more about ASP.NET MVC visit
  13. <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
  14. The page features <mark>videos, tutorials, and samples</mark> to help you get the most from ASP.NET MVC.
  15. If you have any questions about ASP.NET MVC visit
  16. <a href="http://forums.asp.net/1146.aspx/1?MVC" title="ASP.NET MVC Forum">our forums</a>.
  17. </p>
  18. </div>
  19. </section>
  20. }

6.@helper辅助方法

Razor提供了一种很方便的语法,让你可以将View页面中部分内容或部分代码抽取出来,变成一个独立的辅助方法。

  1. @helper ShowUnitPrice(int price)
  2. {
  3. if(price==0)
  4. {
  5. @:免费
  6. }else{
  7. @price
  8. }
  9. }
  1. @foreach(var item in Model)
  2. {
  3. <tr>
  4. <td>
  5. @item.Name
  6. </td>
  7. <td>
  8. @item.Description
  9. </td>
  10. <td>
  11. @ShowUnitPrice(item.UnitPrice)
  12. </td>
  13. </tr>
  14. }

其实声明@helper辅助方法的语法与在C#中声明方法的方式非常像,唯一的差别就在于不用回传任何类型,预设就是网页输出,十分方便。你可以把这种编写风格当成是Razor版的代码片段。

如果要将这个@heper辅助方法用在多个不同的View页面里,你可以考虑将@helper辅助方法独立出来,放置在项目根目录App_Code下,放置在新建的MVC4布局页(Razor)UIHelper.cshtml中。如下所示。

最后再改写原本循环内的@ShowUnitPrice方法,代码如下:

7.@functions自定义函数

@helper辅助方法的确可以很方便地完成辅助方法开发,不过却失去了一些弹性,例如,无法在@helper辅助方法中自定义属性(Property),只能单纯地传入参数,然后格式化成你想要呈现的样子后直接输出。因此,Razor还提供了@functions自定义函数功能,能够让你用接近C#类的方式进一步定义更复杂的辅助方法。

  1. @functions{
  2. public IHtmlString GetYesterday()
  3. {
  4. var theDay = DateTime.Now.AddDays(-1);
  5. return new HtmlString(theDay.ToShortDateString());
  6. }
  7. }

在与@functions同一页里,就能使用上述定义的@GetYesterday()方法来执行。与@helper辅助方法相同,如果希望在多个不同的View页面里都能使用这个由@functions定义的方法,你也可以将这段@functions声明移到项目根目录的App_Code目录下的其中一个cshtml文件里。不过,在搬移@functions代码声明时有一个小地方需要注意,就是必须要声明方法为静态(static)才能让各页面取用,如下。

  1. @functions{
  2. public static IHtmlString GetYesterday()
  3. {
  4. var theDay = DateTime.Now.AddDays(-1);
  5. return new HtmlString(theDay.ToShortDateString());
  6. }
  7. }

8.@model引用参考资料类型

在Razor页面里可以在页面最上方通过@model语法设定一组View页面的强类型数据模型参考,套用了数据模型后,在这个View页面里就可以用具有类型的方式取用Model。

  1. @model IEnumberable<MvcApplication6.Models.Product>

请注意@model语法的第一个字母是小写m,千万不要和Model搞混了。

9.@using引用命名空间

在Razor页面里可以在页面最上方通过@using引用这一个View页面里会用到的命名空间,以简化程序的长度。

  1. @using MvcApplication6.Models
  2. @model IEnumberable<Product>

在ASP.NET MVC项目的Views\web.config配置文件中,有个<system.web.webPages.razor>区段设定,底下有个<namespace>区段设定了所有View页面都会引入的命名空间,如果大部分视图页面都要引用相同命名空间的话,可以在这里设定载入,如此一来,就不用在每页最上方加上@using语法了,如下所示。

  1. <pages pageBaseType="System.Web.Mvc.WebViewPage">
  2. <namespaces>
  3. <add namespace="System.Web.Mvc" />
  4. <add namespace="System.Web.Mvc.Ajax" />
  5. <add namespace="System.Web.Mvc.Html" />
  6. <add namespace="System.Web.Optimization"/>
  7. <add namespace="System.Web.Routing" />
  8. <add namespace="MvcApplication6.Models"/>
  9. </namespaces>
  10. </pages>

知识点2-5:了解Razor语法的更多相关文章

  1. [ASP.NET MVC 小牛之路]03 - Razor语法

    本人博客已转移至:http://www.exblr.com/liam  Razor是MVC3中才有的新的视图引擎.我们知道,在ASP.NET中,ASPX的视图引擎依靠<%和%>来调用C#指 ...

  2. MVC之Razor语法

    Razor是MVC3中才有的新的视图引擎.我们知道,在ASP.NET中,ASPX的视图引擎依靠<%和%>来调用C#指令.而MVC3以后有了一套新的使用@标记的Razor语法,使用起来更灵活 ...

  3. [ASP.NET MVC 小牛之路]03 - Razor语法(转)

    出处:http://www.cnblogs.com/willick/p/3224144.html Razor是MVC3中才有的新的视图引擎.我们知道,在ASP.NET中,ASPX的视图引擎依靠< ...

  4. 【转载】【MVC 学习 Razor语法】

    Razor是MVC3中才有的新的视图引擎.我们知道,在ASP.NET中,ASPX的视图引擎依靠<%和%>来调用C#指令.而MVC3以后有了一套新的使用@标记的Razor语法,使用起来更灵活 ...

  5. Blazor和Vue对比学习(基础1.2):模板语法和Razor语法

    Vue使用模板语法,Blazor使用祖传的Razor语法,从逻辑和方向上看,两者极为相似,比如: 都基于HTML 都通过声明式地将组件实例的状态(数据/方法)绑定到呈现的DOM上 都通过指令实现更加丰 ...

  6. ASP.NET Core 中文文档 第四章 MVC(3.2)Razor 语法参考

    原文:Razor Syntax Reference 作者:Taylor Mullen.Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:何镇汐 什么是 Razor? Razor 是一 ...

  7. MVC Razor语法

    Razor语法, 视图引擎 Razor(CSHTML) @ 可以编写一条C#语句@{} 可以编写一组C#语句,也有可能嵌着Html@: 将文字内容直接输出到页面上去@() 在一句中将一段C#代码包括起 ...

  8. Razor语法&ActionResult&MVC

    Razor代码复用 mvc 4 razor语法讲解和使用 了解ASP.NET MVC几种ActionResult的本质:EmptyResult & ContentResult 了解ASP.NE ...

  9. ASP.NET MVC Razor语法

    ASP.NET MVC Razor语法 (一) 关于_ViewStart.cshtml文件     使用Razor模板引擎的话,会自动生成一个_ViewStart.cshtml文件.事实上,_View ...

随机推荐

  1. LeetCode: Sum Root to Leaf Numbers [129]

    [题目] Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a n ...

  2. c 整数的逆序输出 输入3,2就算 2+22+222的结果

    #include<stdio.h> #include<math.h> //整数逆序输出 void nixu() { int num,i; i = ; scanf("% ...

  3. javaweb学习路之四--cxf发布Webservice

    背景:maven构建的springMvc+mybatis框架 源码--->https://github.com/Zering/MyWeb 步骤:(本步骤是自己在实际探索过程中的步骤,我的思路是先 ...

  4. django开发简易博客(四)

    上一节,我们讲述了怎么使用静态文件,并使用bootstrap对页面进行了美化,这一节我们将增强我们blog的功能,添加发表博客,删除博客的功能. 一.表单的使用 要实现添加blog的功能,就得使用表单 ...

  5. jQuery扩展extend一

    把这个扩展写在这里,以后要是忘了可以回头查看. (function(j) {// 这里的j是一个形参,表示传入的jQuery对象,j可以任意填写 j.extend({// 相当于给jQuery对象加上 ...

  6. Linux学习:netstat命令

    Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态等.对于开发来说,很多时候用于查看端口占用情况. 执行netstat命令,其输出结果可以分成两部分: 1)一是“Active ...

  7. Vijos P1680距离

    题目 背景 简单的DP 描述 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcb_c_”,“_a_bcbcd_”和“ab ...

  8. 【Cocos2d-X开发学习笔记】第03期:渲染框架之导演类(CCDirector)的使用

    本系列学习教程使用的是cocos2d-x-2.1.4版本(截至目前为止最新稳定版) ,PC开发环境Windows7,C++开发环境VS2010 提到“导演”一词,想必读者最先联想到的是电影.作为娱乐产 ...

  9. linux配置nfs服务

    简单介绍: unix/linux系统一种远程文件文件夹共享的服务,能够把某一个远程的文件文件夹共享到本地,进而像操作本地文件一样,操作这个远程的文件夹. 比如:a主机作为服务端,共享出来test1这个 ...

  10. HDU2276 - Kiki &amp; Little Kiki 2(矩阵高速幂)

    pid=2276">题目链接 题意:有n盏灯.编号从1到n.他们绕成一圈,也就是说.1号灯的左边是n号灯.假设在第t秒的时候,某盏灯左边的灯是亮着的,那么就在第t+1秒的时候改变这盏灯 ...