知识点2-5:了解Razor语法

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

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

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

<%: DateTime.Now %>

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

@DateTime.Now

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

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

1.Razor基本语法mvc

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

<p>
    如今时刻:@DateTime.Now
</p>

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

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

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

@{
    var name="Will"; var message="你好,我是 "+name; }

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

    若是要在多行C#代码的Razor语法中插入HTML或其余文字内容,必须在每一行最前面加上一个“@:”符号,并且加上“@:”符号的这行代码里,也能够再加上其余Razor变量。

@{
    var name="Will"; @:你好,我是@name }

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

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

   若是要在Razor视图页面中输出"@"符号。

@@Will_Huang

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

2.Razor与HTML混合输出

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

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

@if (ViewBag.IsEnabled){
    @:启用
} else { @:停用 }

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

@if (ViewBag.IsEnabled)
{
    <span>启用</span> } else { <span>停用</span> }

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

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

复制代码
@if (ViewBag.IsEnabled)
{
    <text> 显示启用的HTML段落: <p> @ViewBag.EnabledMessage </p> </text> } else { <text> 显示停用的HTML段落: <p> @ViewBag.DisabledMessage </p> </text> }
复制代码

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

(1)属性名称误判

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

您好,@ViewBag.Name先生

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

您好,@(ViewBag.Name)先生

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

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

    或修改以下:

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

(2)未预期的额外属性

    要输出以下。

类别是System.Web.Mvc.Controller

    若是按如下输出,会出错。

@{
    ViewBag.MvcNamespace="System.Web.Mvc"; } 类别是@ViewBag.MvcNamespace.Controller

    如何修改?

类别是@(ViewBag.MvcNamespace).Controller

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

    若是咱们要在Razor页面中输出Email超连接,输出的结果多是这样:

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

    这里并不须要改为@@,由于Razor会自动判断先后文,只要"@"的前面与后面都有文字的状况下,@就会停用Razor语法解析,因此在Razor里输入Email是彻底不用编写“@”转义字符。    

    若是要输出的HTML格式以下:

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

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

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

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

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

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

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

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

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

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

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

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

   最后的输出以下:

<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控制项,并将以前母版页面的执行结果填入后输出到用户端。以下所示:

<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这两段声明,而这就是所谓的“挖洞宣言”,以下所示。

复制代码
        </header>
        <div id="body"> @RenderSection("featured", required: false) <section class="content-wrapper main-content clear-fix"> @RenderBody() </section> </div>
复制代码

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

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

@RenderSection("featured", required:false)

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

复制代码
@{
    ViewBag.Title = "Home Page"; } @section featured { <section class="featured"> <div class="content-wrapper"> <hgroup class="title"> <h1>@ViewBag.Title.</h1> <h2>@ViewBag.Message</h2> </hgroup> <p> To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>. The page features <mark>videos, tutorials, and samples</mark> to help you get the most from ASP.NET MVC. If you have any questions about ASP.NET MVC visit <a href="http://forums.asp.net/1146.aspx/1?MVC" title="ASP.NET MVC Forum">our forums</a>. </p> </div> </section> }
复制代码

6.@helper辅助方法

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

复制代码
@helper ShowUnitPrice(int price) { if(price==0) { @:免费 }else{ @price } }
复制代码
复制代码
@foreach(var item in Model) { <tr> <td> @item.Name </td> <td> @item.Description </td> <td> @ShowUnitPrice(item.UnitPrice) </td> </tr> }
复制代码

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

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

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

7.@functions自定义函数

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

复制代码
@functions{
    public IHtmlString GetYesterday() { var theDay = DateTime.Now.AddDays(-1); return new HtmlString(theDay.ToShortDateString()); } }
复制代码

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

复制代码
@functions{
    public static IHtmlString GetYesterday() { var theDay = DateTime.Now.AddDays(-1); return new HtmlString(theDay.ToShortDateString()); } }
复制代码

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

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

@model IEnumberable<MvcApplication6.Models.Product>

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

9.@using引用命名空间

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

@using MvcApplication6.Models
@model IEnumberable<Product>

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

复制代码
   <pages pageBaseType="System.Web.Mvc.WebViewPage"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Optimization"/> <add namespace="System.Web.Routing" /> <add namespace="MvcApplication6.Models"/> </namespaces> </pages>
复制代码
相关文章
相关标签/搜索