MVC-04 视图(1)
不可否认的,View应该是整个ASP.NET MVC项目开发过程中最花时间的部分,因为与显示逻辑相关的技术五花八门,你可能要学习的有HTML、CSS、JavaScript、DOM、JQuery、JSON、Ajax等,当然不只这些,但也不需要全部精通,因为在不同的显示环境下可能会用到不同的技术。
一、关于View的责任
首先来谈谈View的责任,View负责将Controller传过来的资料转换成用户端所需的输出格式,所有在View中出现的代码也应该仅止于“呈现数据”这项工作,不应该还有其他的用途,因此,在View中不应该出现复杂的应用代码逻辑或商业逻辑。
我们在开发ASP.NET MVC时,经常有一句口头禅:“Model要重、Controller要轻、View要够笨”。ASP.NET MVC不希望在开发View时,还需判断过多与View无关的技术,所以在开发时必须尽可能维持View的逻辑简单,千万不要让View承担过多的责任。
二、了解Razor语法
以往开发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页面上输出当前时间的表示法:
<%: DateTime.Now %>
若使用Razor语法,将会变成以下撰写风格
@DateTime.Now
Razor并不是一个代码语言,它只是一种用在View页面的代码区块撰写风格罢了,所写的代码一样是C#或VB.NET,因此开人员并不用额外学习过多的语言只是就你那个快速上手。
若要使用C#语言来编写Razor页面,View页面的扩展名必须使用cshtml才行。同理VB.NET语言,要用vbhtml。
1.Razor基本语法
在页面中输出单一变量时,只要在C#语句之前加上@符号即可。
<p>
现在时刻:@DateTime.Now
</p>
请注意,上述范例中虽然使用C#语言编写代码,但输出单一变量时不需要加上分号结尾。在页面中输出一段含有表达式的结果时,必须在前后加上一个小括号。
<p>
会员名称:@(User.Identity.Name+Model.MemberLevel)
启用状态:@(ViewBag.IsEnabled?"启用":"停用")
</p>
在页面中执行多行C#代码时,必须在前后加上个大括号。
@{
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过的版本如下:
<span style=&#;font-weight:bold;&#;>这是描述文字</span>
如果我们要强迫字符串原封不动地输出,可以利用@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==)
{
@:免费
}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(-);
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(-);
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>
MVC-04 视图(1)的更多相关文章
- ASP.NET MVC——Razor视图引擎
Razor是MVC框架视图引擎,我们今天就来说一说Razor视图引擎. 首先还是来创建一个基础项目叫Razor来演示. 先来定义一个Model叫Product public class Product ...
- 体验 ASP.NET Core 1.1 中预编译 MVC Razor 视图
这是从 ASP.NET Core 1.1 官方发布博文中学到的一招,可以在 dontet publish 时将 Razor 视图编译为 .dll 文件. 需要在 project.json 中添加如下配 ...
- ASP.NET MVC 5 - 视图
在本节中,你要去修改HelloWorldController类,使用视图模板文件,在干净利索地封装的过程中:客户端浏览器生成HTML. 您将创建一个视图模板文件,其中使用了ASP.NET MVC 3所 ...
- asp.net mvc 部分视图加载区别
ASP.NET MVC 部分视图 ASP.NET(11) 版权声明:本文为博主原创文章,未经博主允许不得转载. [部分视图] ASP.NET MVC 里的部分视图,相当于 Web Form 里的 ...
- MVC中视图View向控制器传值的方法
MVC中视图View向控制器传值的方法步骤如下: 1.index页面: 页面中只需要一个触发事件的按钮
- mvc的视图中显示DataTable的方法
mvc的视图中显示DataTable的方法: 不断的循环画出table @{ ViewBag.Title = "ShowDataTable"; } @using System.Da ...
- 第5章——使用 Razor(MVC框架视图引擎)
Razor 是MVC框架视图引擎的名称. 本章提供 Razor 语法的快速教程,以使你能够识别 Razor 表达式. 本章不打算提供 Razor 的完整参考,而将其视为一个语法速成教程.在本书的后续内 ...
- mvc 分部视图(Partial)显示登陆前后变化以及Shared文件夹在解决方案资源管理器中没有显示的问题
刚开始我的解决方案资源管理器中没有显示Shared文件夹,但Shared文件夹在项目中是实际存在的,我搜了下好像没有类似的解答(可能是我搜索的关键词不够准确).后来自己看了下vs2012. 其实解决方 ...
- [转]ASP.NET MVC 5 - 视图
在本节中,你要去修改HelloWorldController类,使用视图模板文件,在干净利索地封装的过程中:客户端浏览器生成HTML. 您将创建一个视图模板文件,其中使用了ASP.NET MVC 3所 ...
- Asp.net MVC Razor视图模版动态渲染PDF,Razor模版生成静态Html
Asp.net MVC Razor视图模版动态渲染PDF,Razor模版生成静态Html 1.前言 上一篇文章我开源了轮子,Asp.net Core 3.1 Razor视图模版动态渲染PDF,然后,很 ...
随机推荐
- 不定高度实现垂直居中(兼容低版本ie)
css实现垂直居中的方法比较多,但是每种方法的缺陷也很明显,我尝试对其中一种方法进行了改良 先看原方法: <div class="parent"> <div cl ...
- javascript中算术运算符规则
javascript中提供了几种算术运算符,+(加) -(减) *(乘) /(除) %(余),常规用法与数学上的一致: 但还规定一些特殊规则: 注:JavaScript中保存数值的方式,可以 ...
- 关于SVM一篇比较全介绍的博文
转自:http://blog.csdn.net/v_july_v/article/details/7624837 支持向量机通俗导论(理解SVM的三层境界) 前言 动笔写这个支持向量机(support ...
- SQL 语句优化—— (一) 操作符优化
1.IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格.但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用IN的SQL有以 ...
- 加深理解UIView,UIResponder,UIController
转载出处:http://www.th7.cn/Program/IOS/201503/406514.shtml 原文地址==>自定义控件:http://objccn.io/issue-3-4/ 读 ...
- BZOJ 1565: [NOI2009]植物大战僵尸( 最小割 )
先拓扑排序搞出合法的, 然后就是最大权闭合图模型了.... --------------------------------------------------------------------- ...
- 兼容现有jQuery API的轻量级JavaScript库:Zepo
Zepo是一个JavaScript框架,其特点是兼容现有jQuery API的同时,自身体积十分小:它与jQuery有着类似的API.如果你会jQuery,那么也就会使用Zepto了. $('div' ...
- spring 入门篇
spring 入门篇 相对于Hibernate(冬眠),Spring(春天),具有更多的诗意与希望的感觉,是为了解决传统J2EE开发效率过低.开发商之间不统一.没有真正实现“写一次到处 ...
- JavaScript中的闭包理解
原创文章,转载请注明:JavaScript中的闭包理解 By Lucio.Yang 1.JavaScript闭包 在小学期开发项目的时候,用node.js开发了服务器,过程中遇到了node.js的第 ...
- linux杂记(⑨)vi使用说明
基本上vi共分为三种模式,分别是[一般模式]].[编辑模式]与[指令列命令模式].这三种模式的作用是: 一般模式:以vi处理一个档案的时候,一进来该档案就是一般模式.在这个模式中,你可以使用[上下左右 ...