介绍“Razor”— ASP.NET的一个新视图引擎【原文地址】 Introducing “Razor” – a new view engine for ASP.NEThtml 【原文发表日期】 July 02, 2010 11:01 PM程序员
个人团队当前正在从事的工做之一就是为ASP.NET添加一个新的视图引擎。web 一直以来,ASP.NET MVC都支持 “视图引擎”的概念—采用不一样语法的模板的可插拔模块。当前ASP.NET MVC “默认”的视图引擎是ASP.NET Web窗体使用的.aspx/.ascx/.master文件模板。而当今其余一些流行的ASP.NET MVC视图引擎还包括 Spark和NHaml。编程 咱们正在打造一个新的视图引擎,它是一个在HTML生成方面进行优化,采用专一于代码的模版解决方案。它的开发代号是“Razor”,第一个beta版本很快就会发布出来。服务器 设计目标在设计和评估“Razor”时,咱们牢记如下几个目标:mvc · 紧凑、富有表现力和流畅:Razor尽可能减小一个文件里须要敲入的字符数,给你畅快淋漓的编码体验。与大部分模板的语法不一样,你不会由于须要在HTML中标注服务器端代码块而中断敲代码的快感。代码分析器足够聪明,可以从你的代码里推断出是否为服务器端代码。这使得其简洁、富有表现力的语法输入可以干净,快速,有趣。asp.net · 上手快: Razor很是容易上手,你只须要了解不多的新东西就能够掌握它,使用你现有的编程语言和HTML知识就足够了。编程语言 · 不是一个新的编程语言:咱们尽可能避免为Razor建立一个新的命令式语言。相反,咱们但愿让程序员只使用现有的C#/VB(或其它)编程语言知识就能使用Razor,咱们只不过在你选择的编程语言里,提供一个很是棒的基于模板生成HTML的标记语法。编辑器 · 可使用任何文本编辑器编写:Razor不要求什么特别的工具,使用老古董的文本编辑器也能够高效编程(“记事本”就不错)。函数 · 很好的智能感应输入提示:虽然Razor不是专为某个工具或者代码编辑器设计的,但它在Visual Studio里仍是有很赞的智能提示功能。咱们将会升级Visual Studio 2010和Visual Web Developer 2010使得它具备完整的编辑器智能提示功能。 · 便于单元测试:新的视图引擎支持对视图执行单元测试,不须要控制器(controller)或者Web服务器,并且能够包含在任意的单元测试项目中—不须要单独的应用程序域(App-Domain)。 过去几个月,咱们一直在用Razor来编写程序,并邀请了一些志愿者(包括好几组非.NET的 Web程序员)来作易用性研究。使用过它的人对它的评价都不错。 弹性的选择空间ASP.NET最赞的地方之一就是大部分组件都是可插拔的。若是你发现有一个组件很差用,随时均可以换成另一个。 ASP.NET MVC的下一个版本将会包括一个新的“添加->视图”对话框,它让你能够方便地在建立新的视图模板文件时选择你想要使用的语法。它还便于你选择任一个安装在机器上的视图引擎—选择你感受最天然的视图方案: Razor将会是ASP.NET MVC内置的视图引擎之一。全部的视图辅助(helper)方法和编程模型特性同时支持Razor和.ASPX视图引擎。 你还将能够在单个站点或程序中混合使用多个视图引擎写的视图模板。好比说,你能够编写一些视图,有些用.aspx文件,有些用.cshtml或者.vbhtml文件(分别是Razor的C#和VB版本的文件后缀名),而另一些用Spark或者NHaml。你还能够在采用一种视图引擎的视图模板里包含用另外一种引擎编写的局部视图模板。总之,你有灵活的选择空间。 Razor版的“Hello World”Razor容许你从静态的HTML页面(或者任意的文本内容)开始,添加服务器端代码使其变成动态页面。Razor的一个核心设计理念就是使编码过程更加流畅,而且只要最少的按键次数就能快速地在HTML标记中添加服务器端代码。 让咱们来建立一个简单的例子:“hello world”,它的最终输出以下图所示: 使用.ASPX“代码碎块 [ii]”的方式编写 若是用现有ASP.NET的.ASPX标记语法来编写上面的“Hello World”示例的话,咱们须要在HTML标签中使用”<%= %>”来标记“代码碎块”: 仔细观察就能够发现上例中每个代码碎块都须要5个字符(”<%= %>”)来标明代码的开始和结束位置。并且其中还有几个字符在键盘上不是特别好敲到(特别是“%”键—它位于大部分键盘的中上部)。 使用Razor的语法编写 在Razor中,你只须要用一个”@”字符就能够标识代码块的开始,与”<% %>”代码碎块不同,Razor不须要你显式指明代码块的结束位置: Razor分析器懂得代码块中使用的C#或VB的语法—这就是为何上例中咱们不须要显式关闭代码块的缘由。Razor能够自动识别出上面的语句是独立的代码块并悄悄地为咱们关闭它们。 看看,即便是像“hello world”这样微不足道的例子就为咱们节省了12次键盘敲击。并且在键盘上”@”字符还比”%”字符更容易按,敲起来更快也更流畅。 循环和内嵌HTML示例 让咱们来看看另一个简单的场景,好比说要列出一些商品(并在每样商品旁标明价格): 用.ASPX”代码碎块”编写 若是用ASP.NET现有的.ASPX标记语法,咱们可能须要写相似下面的代码来动态生成一个<ul>列表,里面包含表示每一个商品的<li>元素: 使用Razor语法 下面是生成一样输出的Razor版本的代码: 请注意上面”@”符号是如何开始一个“foreach”循环,并在循环内嵌入一行包含代码块的HTML语句的。由于Razor分析器知道咱们在代码块里用的C#语法,它能够识别出<li>标签里的内容应该被包含在foreach代码块中,并循环处理它们。它甚至还知道末尾的“}”结束foreach循环。 Razor很聪明,还能识别出<li>标签内的@p.Name和@p.Price是服务器端代码—而且在每次循环时执行它们。另外请留心Razor在HTML和代码混合的状况下,还能推导出@p.Name和@p.Price代码块的结束位置。 不须要在你的模板中添加许许多多打开/关闭标记来编写代码的感受果真是酣畅淋漓。 If代码块和多行语句 下面是其余几个常见的场景: If语句 跟上面的foreach示例同样,你能够在if语句中直接嵌入内容(或其余C#或者VB语言元素),而不须要显式指明代码块的开始和结束位置。例如: 多行语句 你能够像下面这样,使用“@{ 代码 }” 标注多行语句: 请注意上例中,变量能够被多个代码块引用—变量“message”在包含多行语句的“@{}”块中定义,但也能够被@message代码块使用。这个跟.aspx文件里的”<% %>”和”<%= %>”的语法相似。 多符号语句 “@()”语法容许代码块中有多个符号,例如,咱们能够把上例中链接字符串和数字的代码使用”@ ()” 代码块这样重写: 集成代码和内容 Razor解析器内置了不少语言智能—脏活累活帮你作。 在HTML里,它会不会影响”@”符号在电子邮件地址和其余地方的用法? 大部分状况下,Razor解析器都有足够的能力推导出模板里的一个“@”字符究竟是在代码中用到,仍是在静态内容中用到。例如,我在下例中的邮件地址中使用了”@”字符:
当解析文件时,Razor会分析”@”字符右边的内容来判断它究竟是代码(若是是CSHTML文件的话那就是C#代码,而若是是VBHTML文件的话那就是VB代码)仍是静态文本内容。上例中的代码会输出如下的HTML(邮件地址被看成静态内容输出,而@DateTime.Now就被看成代码执行了):
若是碰到和代码同样格式的内容(或者你想把代码看成内容看待),你能够显式地打@@来用另一个”@”字符进行转义。 识别内嵌的内容 当在一个if/else,foreach或者其余块语句中内嵌HTML文本时,能够考虑用一个HTML或XML标签将嵌套内容环绕起来,这样能够更清楚地标明一个文本内容块的开始。 例如,下例我使用<span>标签包围多行文本内容,而文本里还有一个代码块:
在客户端的显示结果以下—注意那个<span>标签:
若是你不想在显示文本内容时,把外面的标签也输出到客户端,那能够考虑使用<text>将嵌套内容括起来:
上面的代码在客户端的输出结果以下—请注意外面的<text>标签没有被输出:
HTML编码 默认状况下,”@”语句块生成的内容会自动对HTML代码进行过滤和转换 [Yimin1] ,用来更好地防范XSS垮站脚本攻击。 版面设计/母版页的状况—基础篇在站点中保持一致的页面观感风格很是重要。ASP.NET 2.0引入了“母版页面(master page)”的概念,就是用来帮助在使用基于.aspx的页面或模板时实现这个功能。Razor一样也支持这个概念,它用的是“版面设计页面(layout pages)”—你能够先定义一个通用的站点模板,而后在站点其余视图或页面继承模板定义的统一观感。 版面设计的一个简单示例 下面是一个简单的版面设计页面示例,文件将会被保存为“SiteLayout.cshtml”。它包含了全部要放在页面里的静态HTML文本内容和动态的服务器端代码。接着咱们添加了一个名为“RenderBody()”的辅助函数,放在模板中须要根据所请求的URL而“填入”具体内容的地方: 接下来咱们再建立一个名为“Home.cshtml”的视图模板,它只包含了必要的文本内容和代码来构成所请求页面的具体内容,外围的内容则由版面模板提供: 请留意上面在Home.cshtml文件中咱们怎么来显式地设置“LayoutPage”属性。它指明了咱们指望用SiteLayout.cshtml做为这个视图的版面设计模板。咱们还能够在ASP.NET MVC 控制器(Controller)调用Home.cshtml这个视图模板的时候,能够指定这个版面设计文件,或者将其配置为站点默认的版面设计模板(这种状况下,咱们只须要在项目中的一个文件中指定它,而全部的视图模板都会自动采用它)。 当咱们将Home.cshtml做为一个视图模板显示时,它会合并版面设计页和子页面的内容,而后将下面的内容发送到客户端: 简洁、清晰、富有表现力的代码 上例中值得注意地方的还有一点,就是版面定义和在视图/页面中使用它们的语法既清晰又简练。上面列出的SiteLayout.cshtml和Home.cshtml代码截图已经包含了两个文件全部的代码—没有额外的配置步骤或冗余的标签,没有<%@ Page %>前缀,也不须要设置其它的标签或者属性。 咱们尽力使编写出来的代码简洁流畅。咱们还但愿任何人均可以在一个文本编辑程序中打开、编辑和调整/自定义它们。不须要代码生成或者智能提示(Intellisense)。 版面设计页面/母版页的状况—覆写部份内容版面设计页面能够有选择性地定义几个不一样的“节”,容许基于这个版面设计的视图模板经过“填入”自定义的内容来覆写它。这就容许你在视图中覆写版面设计页里不连续的内容段落,从而使你的站点版面设计更有弹性。 例如,咱们回到SiteLayout.cshtml文件,并在其中定义两个节,这样视图模板能够有选择性的填充这两个节。咱们将节的名称命名为“menu”和“footer”—而后在RenderSection()辅助函数传入optional=true这个参数来代表它们是可选填充节(咱们能够用C#最新的 optional参数语法来作这件事情,我在前面的 博客里也提到了这个用法)。
由于两个节被标记成了“可选”,不须要在Home.cshtml文件中定义它们。即便没有它们,站点依然能够正常工做。 让咱们回到Home.cshtml并自定义Menu和Footer节。下面的截图包含了Home.cshtml里全部的内容—再没有其它内容了。注:我已经把LayoutPage设置为站点范围的默认模板了—因此它没有显示在里面。
咱们覆写的”menu”和“footer”节定义在文件里的以相应的名字命名的@section { }块里面。咱们刻意不要求你在节里包含“main/body”内容,相反将它们内联在页面里(除了节省键盘敲击的次数之外,还便于你在版面设计页面中添加新的节之后,不须要再回去修改全部已有页面的语法)。 当再次将Home.cshtml以视图模板的形式显示的时候,它如今会合并版面设计页和子页面里的内容,并将两个自定义节覆写的内容整合进来,最终发送到客户端的内容以下:
封装和重用HTML辅助函数咱们刚刚讲过如何使用版面设计页给站点提供统一的观感。如今让咱们看看如何经过建立可复用的“HTML辅助函数”来把生成HTML的功能封装成一个函数库,这样能够在整个站点复用—甚至在多个站点复用。 基于代码的HTML辅助函数 ASP.NET MVC有一个“HTML辅助函数”的概念—封装了生成HTML的逻辑并能够用在代码块里的函数。它们当前还都是纯粹经过代码实现的,通常经过扩展函数(Extension Method)实现。现有的全部内置在ASP.NET MVC里的HTML扩展函数均可以使用在“Razor”视图引擎里(不须要修改任何代码):
声明式的HTML辅助函数 使用纯代码的类来生成HTML能够工做—但不是很理想。 咱们来看Razor的另一个特性,使用简单的更具描述性的方法建立可复用的HTML辅助函数。咱们计划让你可使用相似下面的 @helper { }声明式语法建立可复用的辅助函数: 你将能够把包含有这种辅助函数的.cshtml文件放到一个Views\Helpers文件夹,而后就能够在站点上使用它们了(再没有其它的步骤了):
请注意上例中咱们能够为ProductListing()函数定义参数。这样你就能够为函数传入任意的参数了(并且还能彻底利用可选参数,nullable类型,范型等现有编程语言的特性),另外还有Visual Studio强大的调试支持。 注:@helper语法在Razor的第一个beta版里尚未—但咱们但愿能在下一个发布里把它包含进来。基于代码的辅助函数在第一个Beta版本里就可使用。 传入内联模板做为参数 Razor中另外一个颇有用(或者能够说是至关了得)的功能就是容许向辅助函数传入“内联模板”参数。这些“内联模板”能够同时包含HTML和代码,并且能够被辅助函数即行调用。 下例中的“Grid”HTML辅助函数就是经过这种技术在客户端呈现一个DataGrid:
上例中Grid.Render()函数调用使用的是C#语法。咱们使用了新的语法— C#命名参数把强类型的参数传给Grid.Render函数。这同时也意味着咱们可使用所有智能提示,还有编译时的语法检查功能。 在定义列的时候传给“format”参数的就是一个“内联模板”—它同时包含了自定义的html和代码,它们是用来自定义数据的显示方式的。更厉害的是,Grid辅助函数能够把咱们的 “内联模板”看成一个委托来调用,想几时调用就几时调用,想调用多少次就调用多少次。在上面的场景里,每呈现grid的一行,就会调用它一次—并经过传入“item”变量,以便咱们的模板能够显示恰当的内容。 这个功能容许你开发功能更强大的HTML辅助函数。从此你既可使用代码方式(跟如今建立扩展函数的方式同样),也可使用声明式的@helper { }方式来编写HTML辅助函数。 对Visual Studio的支持前面说过,Razor的一个目标就是尽可能减小键盘敲击次数,并且使用普通的文本编辑器就能够编写(记事本就很不错了)。咱们经过保证语法清晰简单干练来实现这个目标。 Visual Studio也支持Razor, 使你在里面编写Razor代码时感受更丰富。对于基于Razor的源文件,咱们提供了完整的HTML、JavaScript和C#/VB代码智能提示功能:
请注意,上面咱们甚至为嵌入在foreach循环体里面<li>元素的Product对象的“@p.”启用了智能提示。另外还要注意的地方是,在“解决方案资源管理器”的“\View”文件夹里,同时存放了.aspx和.cshtml视图模板。你能够在单个程序中使用多个视图引擎—便于你选择最适合你的引擎。 总结咱们认为“Razor”是一个很是好的新的视图引擎,它提供了流畅的专一于代码的模版方案。它的编码工做流快速、富有表现力并有趣。语法简练并节省按键次数,同时还提高了代码的可读性。它会做为内置的视图引擎并随下一个版本的ASP.NET MVC发布。你也能够把单独的.cshtml/.vbhtml放到程序里,并把它们看成独立的页面执行—这样你就也能够在ASP.NETWeb窗体程序中使用它了。 前几个月里,试用过它的开发人员对它的评价都很是好。咱们立刻就要发布它的第一个beta版,并期待收到您对它的反馈。 但愿这能对您有所帮助。 Scott |