本章学习内容
1.MVC3的新特性之Razor视图解析
上一章说到过控制器只是用来提供页面数据源的,所有的展示还是在Views里进行,各种Css和js的效果也是在此一展伸手的。
展开Views>Hoem文件夹,我们可以看到里面有两个文件
这两个cshtml的文件与我们以往的asp.net webform应用程序见到的文件不太一样,既不是aspx也不是html,这就是MVC3的新特性Razor视图引擎的视图文件,在MVC1和MVC2里,视图仍然是我们熟悉的aspx文件的,即使在MVC3里,也可以选择aspx作为视图引擎,在创建项目时大家应该都看到过了。不过微软既然雄心勃勃的推出了Razor视图,自然说明Razor视图是有他的优势的,接下来我们来一探究竟。
Razor有着非常简单和干净的语法,以下内容摘自微软官方人士介绍
在设计和评估“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视图和它的一些语法:
Razor的语言简单之极,只需记住一个字符就可以:@。
在传统的ASP.NET视图引擎中,如果我们要进行一些数据绑定或者逻辑判断就会使用类似下面的做法:
<%var testStr1 = "Hello";var testStr2 = "lengleng";%>
我们先搞了两个变量,当然,这些变量可以从任意的地方获得,然后,我们将这两个变量绑定到页面中去:
<%=testStr1 %>,Your name:<%=testStr2 %>
不知道您看的如何,总之我感觉是够乱的。
同样的东西,我们用Razor的语法来重写,会是怎么样的呢?(为了着色,直接贴图片了)
当然了,结果是一样的,不过在表现力上显然Razor更胜一筹,因为来回的<%%>看的人眼花,例如下面这个MVC中登陆部分的用户控件:
<%if (Request.IsAuthenticated) {%>欢迎您,<b><%: Page.User.Identity.Name %></b>! [ <%: Html.ActionLink("注销", "LogOff", "Account") %> ]<%}else {%>[ <%: Html.ActionLink("登录", "LogOn", "Account") %> ]<%}%>
我唯一的感觉:晕!用Razor后:
是不是更加的人性一些呢?唯一需要说的就是@:,这是说它后面的内容是混合内容,即有纯文本又有服务器端代码。不过上面的代码我没有做过测试,这是改成了Razor的样式,所以大家谨慎参考。
Helper
严格的讲这部分不能算语法层面上的特性,只能算是支持Razor的辅助类库。因为Razor实在过于简单了,说白了就一个@,只要会C#或才VB.NET就行,以前的知识全部能用。
- 类似于传统ASP.NET的母版页、用户控件机制
在呈现类似用户控件的内容时(说白了就是用户控件),可以使用RenderPage辅助类,例如:
而所谓的“用户控件”其实就是一个没有<html><head><body>的裸页,将经常会使用的一部分逻辑或者内容分离出来以达到复用。
母版页可以提供统一的外观,按照原来的思路,一般会在母版页中插入ContentPlaceHolder控件来指明哪部分是要被使用页来替换内容的,在Razor中,它不叫ContentPlaceHodler,叫RenderBody。
不同的时,传统ASP.NET可以在母版页中插入多个ContentPlaceHolder,而RenderBody只能有一个。其实,类似ContentPlaceHolder,Razor中也提供RenderSection来实现。
先说RenderBody。当我们在母版页中的某个位置写了@RenderBody()后,接下来在使用母版页时,只需在页面的顶部写入:
@{ LayoutPage = "MasterPageLocation"; },这样,接下来的内容会自动填充到母版页RenderBody()对应的位置:
MasterPage:
Page:
这些都是Razor视图的一部分功能展示,具体的我们在后续项目中遇到了会再做解释,想了解更多的可以参见
http://msdn.microsoft.com/zh-cn/ff849693 和http://blog.renren.com/share/260355823/2829674153
现在回到我们的项目,双击打开Views>Home>Index.cshtml,内容如下
@{ ViewBag.Title = "主页"; } <h2>@ViewBag.Message</h2> <p> 若要了解有关 ASP.NET MVC 的更多信息,请访问 <a href="http://asp.net/mvc" title="ASP.NET MVC 网站">http://asp.net/mvc</a>。 </p>
此处并没有找到我们对应的Hello World字符串,但是他有一段代码是@ViewBag.Message,这与我们的控制器里有些像,右键页面任意处,转到控制器
界面会自动跳转到该视图对应的Action中,这里也体现出来“约定胜于配置”原则的重要和便利。
我们可以看到Index Action中使用了ViewBag.Message = "Hello World!";这样的代码,那么到了这里页面的显示过程就不言而喻了。系统访问了Home的Index Action,在此Action中我们给ViewBag.Message赋值,然后使用 return View()返回该Action对应的Home/Index.cshtml视图里进行显示,显示该数据的调用方法就是Index.cshtml 中的@ViewBag.Message。
那么说到此处,或许有人要问,ViewBag是什么东西,为什么它可以做数据传递的载体,下面我们会用代码说明
修改HomeController文件代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MyShopTest.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Hello World!"; ViewBag.MyName = "韩若怅"; ViewBag.ProjectName = "我的商店"; return View(); } public ActionResult About() { return View(); } } }
右键该Ation任意处,点击转到视图
进入对应视图,修改视图Index.cshtml代码如下
@{ ViewBag.Title = "主页"; } <h2>@ViewBag.Message</h2> <br /> 项目创建人:@ViewBag.MyName <br /> 项目名称:@ViewBag.ProjectName <p> 若要了解有关 ASP.NET MVC 的更多信息,请访问 <a href="http://asp.net/mvc" title="ASP.NET MVC 网站">http://asp.net/mvc</a>。 </p>
重新编译项目,F5运行项目,可以看到如下结果
我们成功将数据传递到了前台,很明显,在此过程中我们定义的 ViewBag.MyName和ViewBag.ProjectName并不是c#的任何关键字,ViewBag也不可能预置好这么多关键字来让我们随时赋值随时调用,那么ViewBag是什么就呼之欲出了。
在MVC 3中的有一个新的ViewBag 动态特性,它主要是为了从Controller到view进行传值用的,类似有所使用的ViewData[] 字典类。对于ViewBag是如此的强大,意味着你能动态的set/get 值,增加任何数量的的额外字段而不需要强类型的检测,系统会自动根据你传入的值在运行时动态解析
为了看的更明白,我们再次修改Home控制器代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MyShopTest.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Hello World!"; ViewBag.MyName = "韩若怅"; ViewBag.ProjectName = "我的商店"; List<string> list = new List<string> { "测试ViewBag作用"}; ViewBag.List = list; return View(); } public ActionResult About() { return View(); } } }
修改Index对应视图代码如下
编译项目,运行,可以看到ViewBag的动态对象可以将任何对象赋给他,取值时也不需做任何类型转换,因为它是动态类型解析的。
在讲述ViewBag时,上文提到了一个ViewData[]数据字典,它也是用于页面和Action传值的一个重要对象,既然是数据字典,使用方法也就很简单了,无非是ViewData[Key]=Value;
但是它和ViewBag有一定区别的,我们也在此讲述一下,以便大家更好的使用二者。
以下实例为摘抄
Eample:--using ViewBag
Controller
- public ActionResult Index()
- {
- List<string> colors = new List<string>();
- colors.Add("red");
- colors.Add("green");
- colors.Add("blue");
- ViewData["listColors"] = colors;
- ViewData["dateNow"] = DateTime.Now;
- ViewData["name"] = "Hajan";
- ViewData["age"] = 25;
- return View();
- }
View (ASPX View Engine)
- p>
- 02 My name is
- 03 <b><%: ViewData["name"] %></b>,
- 04 <b><%: ViewData["age"] %></b> years old.
- 05 <br />
- 06 I like the following colors:
- 07 </p>
- 08 <ul id="colors">
- 09 <% foreach (var color in ViewData["listColors"] as List<string>){ %>
- 10 <li>
- 11 <font color="<%: color %>"><%: color %></font>
- 12 </li>
- 13 <% } %>
- 14 </ul>
- 15 <p>
- 16 <%: ViewData["dateNow"] %>
- 17 </p>
Eample :-Using ViewBag
Controller
- public ActionResult Index()
- 02 {
- 03 List<string> colors = new List<string>();
- 04 colors.Add("red");
- 05 colors.Add("green");
- 06 colors.Add("blue");
- 07
- 08 ViewBag.ListColors = colors; //colors is List
- 09 ViewBag.DateNow = DateTime.Now;
- 10 ViewBag.Name = "Hajan";
- 11 ViewBag.Age = 25;
- 12 return View();
- 13 }
你和上面的对比 你看见了不同吗?
View (ASPX View Engine)
- <p>
- My name is
- <b><%: ViewBag.Name %></b>,
- <b><%: ViewBag.Age %></b> years old.
- <br />
- I like the following colors:
- </p>
- <ul id="colors">
- <% foreach (var color in ViewBag.ListColors) { %>
- <li>
- <font color="<%: color %>"><%: color %></font>
- </li>
- <% } %>
- </ul>
- <p>
- <%: ViewBag.DateNow %>
- </p>
在上面的例子以内ViewBag是动态类型的,所以我没有必要把 ViewBag.ListColors 转换成如 List<string>这样子的形式。另一方面,这个ViewData["key"]是一个对方。
如果你在你的Controller中使用ViewData["ListColors"]=Colors,那么你可以在View试图中通过ViewBag.ListColors来检索它们。
有兴趣的可以参考http://blog.csdn.net/asdwww007/article/details/6825553,讲的很好。
视图,控制器,路由部分到此就结束了,请大家一定要深刻了解这几章的内容,接下来就会进入我们正式的项目编码了。