介绍“Razor”— ASP.NET的一个新视图引擎

我的团队当前正在从事的工作之一就是为ASP.NET添加一个新的视图引擎。

一直以来,ASP.NET MVC都支持 “视图引擎”的概念—采用不同语法的模板的可插拔模块。当前ASP.NET MVC “默认”的视图引擎是ASP.NET Web窗体使用的.aspx/.ascx/.master文件模板。而当今其他一些流行的ASP.NET MVC视图引擎还包括 Spark和 NHaml。

我们正在打造一个新的视图引擎,它是一个在HTML生成方面进行优化,采用专注于代码的模版解决方案。它的开发代号是“Razor”,第一个beta版本很快就会发布出来。

设计目标

在设计和评估“Razor”时,我们牢记以下几个目标:

· 紧凑、富有表现力和流畅:Razor 尽量减少一个文件里需要敲入的字符数,给你畅快淋漓的编码体验。与大部分模板的语法不同,你不会因为需要在HTML中标注服务器端代码块而中断敲代码的快 感。代码分析器足够聪明,能够从你的代码里推断出是否为服务器端代码。这使得其简洁、富有表现力的语法输入能够干净,快速,有趣。

· 上手快: 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版,并期待收到您对它的反馈。

希望这能对您有所帮助。

【原文地址】 Introducing “Razor” – a new view engine for ASP.NET

【原文发表日期】 July 02, 2010 11:01 PM

转载于:https://www.cnblogs.com/X-Jonney/p/4635051.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/375759.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

w10系统打印服务器怎样出来,win10怎么打开关闭打印机服务教程步骤

当我们想要使用打印机服务时候&#xff0c;却不知道在哪里打开&#xff0c;对于win10系统&#xff0c;具体怎么操作呢?下面小编来告诉你开启和关闭打印机服务的方法吧&#xff0c;希望对你有帮助!Win10系统开启和关闭打印机服务的方法1、在Win10系统下&#xff0c;按住键盘的“…

MongoDB系列二

简介 MongoDB是一个基于分布式文件存储的数据库。由C语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB是一个高性能&#xff0c;开源&#xff0c;无模式的文档型数据库&#xff0c;是当前NoSql数据库中比较热门的一种。 MongoDB是一个介于关系数据库和非关…

C++11的静态断言

断言就是将一个返回值总是需要为真的判别式放在语句中&#xff0c;来排除在设计的逻辑上不应该出现的情况。C11标准中引入了静态断言&#xff1a;static_assert 在C标准中&#xff0c;<cassert>或assert.h为我们提供了assert宏&#xff0c;但是这个宏只有在运行时才进行…

C# DataTable去除重复,极其简便、简单

其中sourceDT是获取到的一个DataTable类型的集合对象 去重复使用方式&#xff1a; 实例化一个DataView对象 假设为dv&#xff0c;直接dv.ToTable()即可&#xff0c;ToTable中可为&#xff08;true,"用于判断重复的列"&#xff09;&#xff0c;比如图中所示&#xff0…

环形矩阵

1.逆时针 代码&#xff1a; 1 // huanxingjz.cpp : Defines the entry point for the console application.2 //3 4 #include "stdafx.h"5 #include <stdio.h>6 #include <iostream>7 #include "windows.h"8 #define MAX 409 using namespace …

Winsock网络编程笔记(4)----基本的理论知识

前面的笔记记录了Winsock的入门编程&#xff0c;领略了Winsock编程的乐趣。。但这并不能算是掌握了Winsock&#xff0c;加深理论知识的理解才会让后续学习更加得心应手。。因此&#xff0c;这篇笔记将记录一些有关Winsock的基本理论知识&#xff0c;由于是一篇笔记&#xff0c;…

Method Swizzle黑魔法,修改 ios 系统类库方法(转载)

一般来说&#xff0c;系统提供的方法已经足够开发了&#xff0c;但是有的时候有些需求用普通方法不好做。 如&#xff1a;在所有的viewcontroll 的viewwillappear&#xff1a;方法之前打个log 你可能会这么做&#xff1a; 1. 建一个uiviewcontroll 父类&#xff0c;重写viewwil…

win10无法开启夜间模式

在学校的时候没感觉&#xff0c;一进公司发现电脑还是需要设置一下护眼的&#xff0c;但是在设置的时候却遇到夜间模式无法开启的问题。 首先在左下角搜索设备管理器 找到显示适配器 查看显示器设备状态 如果设备图标上有黄三角感叹号则说明该设备驱动有问题&#xff0c;需要…

项目管理工具到底应该为谁服务?

项目管理工具到底应该为谁服务&#xff1f;为管理者&#xff0c;还是为了团队&#xff1b;为了管理报表&#xff0c;还是为了协作需求&#xff0c;这些是在项目管理工具选择或开发时需要面对和思考的一个问题。 传统项目管理工具在团队内部臭名昭著 项目管理工具当初都是为了项…

二叉树的递归定义及存储

定义 最多有两棵子树的有序树&#xff0c;称为二叉树。二叉树是一种特殊的树。 递归定义&#xff1a;二叉树是n(n>0)个有限结点构成的集合。N0称为空二叉树&#xff1b;n>0的二叉树由一个根结点和两互不相交的&#xff0c;分别称为左子树和右子树的二叉树构成。 二叉树中…

NetBpm 安装篇(1)

尊重别人劳动成果 转载注明出处&#xff1a;http://www.cnblogs.com/anbylau2130/p/3875718.html 官方主页 http://www.netbpm.org/docs/install.html 文件目录 Netbpm的两种服务器配置 1&#xff0c;CassiniWebServer CassiniWebServer.exe是轻量级的web服务器&#xff0c;相…

python将文本中的数据处理成图像(matplotlib)

使用Python的matplotlib模块可以很方便的将数据处理成图表&#xff0c;使数据更加形象、直观。 #!/usr/bin/env pythonimport matplotlib.pyplot as plt import numpy as np from mpl_toolkits.axes_grid.anchored_artists import AnchoredTexty1np.loadtxt(ReadDataCostTime.…

交叉编译android版htop

编这个东西贼烦人。 话不多说&#xff0c;直接上教程 源代码版本&#xff1a;htop-2.2.0、ncurses-6.1 编译之前要确认自己有ndk&#xff0c;从【官网】直接下载&#xff0c;下载下来解压一下就能用。 先编ncurses 编译过程 ./configure CCarm-linux-androideabi-gcc-4.9 \-…

UITableView知识梳理须知—(一)

1、UITableView掌握 1> 设置UITableView的dataSource、delegate 2> UITableView多组数据和单组数据的展示 3> UITableViewCell的常见属性 4> UITableView的性能优化&#xff08;cell的循环利用&#xff09; 5> 自定义Cell 2、什么是UITableView 在i…

Yarn中的几种状态机

1 概述 为了增大并发性&#xff0c;Yarn采用事件驱动的并发模型&#xff0c;将各种处理逻辑抽象成事件和调度器&#xff0c;将事件的处理过程用状态机表示。什么是状态机&#xff1f; 如果一个对象&#xff0c;其构成为若干个状态&#xff0c;以及触发这些状态发生相互转移的事…

分支管理(转载)

转自&#xff1a;http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013743862006503a1c5bf5a783434581661a3cc2084efa000 分支就是科幻电影里面的平行宇宙&#xff0c;当你正在电脑前努力学习Git的时候&#xff0c;另一个你正在另一个平行…

分享一个用安卓手机就能引导pc安装linux系统办法

1、首先安卓手机下载软件DriveDroid.apk http://pan.baidu.com/s/1qW4pbT6 2、下载linux镜像文件放手机存储卡存储&#xff0c;放到Download/images/以下 3、打开软件会自己主动读取这个目录以下镜像&#xff0c;也能够在软件里面下载须要的镜像文件 4、软件设置usb连接模式 5、…

SharePoint 2013 开发——其他社交功能

博客地址&#xff1a;http://blog.csdn.net/FoxDave上一篇讲了如何获取用户配置文件的相关属性&#xff0c;它属于SharePoint 2013社交功能的一个小的构成部分。社交功能是SharePoint 2013改进的一大亮点。可以在现有网站上开启社交功能或者新建一个专门用于社交用途的社区网站…

第一个Qt+opencv程序

简单安装好Qt和编译安装好opencv后&#xff0c;简单实现第一个Qtopencv程序&#xff1a;读取并显示一张图片&#xff0c;这里我的Qt版本时5.9.1&#xff0c;opencv版本是4.0.1&#xff0c;版本的影响不大。 首先我们用Qt创建一个控制台项目&#xff0c;即在创建项目时选择Qt C…

redis学习笔记——应用场景

最近在看redis入门指南&#xff0c;现在就自己的学习情况说说自己的理解。 字符串类型&#xff08;String&#xff09; 字符串类型是Redis中最基本的类型&#xff0c;能存储任意形式的字符串&#xff0c;包括二进制数据。如一张照片也可以用字符串类型存储。注意字符串类型键允…