到了View的呈现板块,感觉ASP.NET MVC的学习也进入了尾声,还是比较开心的,毕竟也有了不小收获。这部分内容相对比较简单,因为之前还专门学习过如何结合HTML5与MVC框架。前文中提到过,ActionResult的执行实际就是View呈现的入口。不同类型的ActionResult比较多,以下做个简要的介绍。

类型 简介
EmptyResult 最简单的Result,只是为了符合框架的流程。
ContentResult 可以设置ContentType为javascript, CSS等,默认将基本类型的返回值转化为ContentResult。
FileResult 包含FileContentResult, FilePathResult, FileStreamResult
JavascriptResult 在服务端动态生成javascript并作为请求的相应。
JsonResult 提供对象和Json字符串的序列化与返序列化
HttpStatusCodeResult 方便返回Http状态码
RedirectResult RedirectToRouteResult 前者是我们可以直接重定向到指定的目标地址,后者帮助我们根据注册的路由进行重定向,不提供URL参数,而提供RouteName和RouteValues。类似httpResponse的Redirect/RedirectPermanent,在SEO中,前者会使永久重定向目的地址更新为搜索引擎的索引,后则不会。

接下来介绍最重要的ViewResult以及VIewEngine的概念。View实现IView接口,其实就是一个Render方法,参数ViewContext除了常见属性外,还有两个与js相关属性(CleintValidationEnabled, UnobstrusiveJavascriptEnabled),特别的是object类型的ViewBag用了[Dynamic]特性。ViewEngine也实现了相应的接口,注意View缓存,SearchedLocations属性包含了所有的查找路径,FindView方法的的返回名称比较奇怪,ViewEngineResult,但实际的意思应该是这个Result包含View和ViewEngine信息。在另一篇管自定义ViewEngine的博文中对这一块进行了更加深入的介绍。

再则简要的介绍下Razor引擎,我们知道.cshtml文件并不能直接执行,必须先动态编译后才能使用,那么问题来了,编译成什么文件的文件名是什么,所属的程序集为什么?并存放在哪呢?

文件名为:ASP_Page_views_XXX_ActionXXX_cshtml

程序集名由代码可知:

 public static MvcHtmlString ListViewAssemblies(this HtmlHelper helper)
{
TagBuilder ul = new TagBuilder("ul");
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.StartsWith("App_Web_")))
{
//omit
}
return new MvcHtmlString(ul.ToString());
}

编译的临时文件的路径为:

"%WinDir%\Microsoft.NET\Framework\{VersionNo}\Temporary ASP.NET Files\"

可以通过如下配置,变更路径:

 <system.web>
<compilation tempDirectory="C:\XXXXXXXX"/>
</system.web>

补充一个获得编译后类型和程序集的方法,使用BuilderManager类型的静态方法GetCompiledType和GetCompiledAssembly。

View文件编译生成的类型为WebViewPage<TModel>,也就是说.cshtml编译后的类型均为以上类型。其基类WebPageExecutingBase包含Execute, Write, WriteLiteral等方法。该基类的另一个自雷WebPageRendingBase包含Layout, IsAjax, Server, Session, Profile, Cache等属性,以及输出整个页面的抽象方法ExecutePageHierarchy。

WebViewPage还有一个直接基类WebPageBase,它实现类抽象方法ExecutePageHierarchy,最终呈现的页面包含3部分内容:布局文件、开始页面View本身。蒋老师提供的一个不错的布局例子代码如下所示:

 //布局文件定义
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
@{if (IsSectionDefined("Header"))
{RenderSection("Header");}
else
{<h2>@ViewBag.Title</h2>}
@RenderBody()
@{ if(IsSectionDefined("Footer")){
@RenderSection("Footer");
}
else{<hr/><p>@ Xixi. All rights reserved.</p>}
}}
</body>
</html> //View的定义
<div>
<p>Bilibili</p>
</div>
@section Header
{<h2>Bili bili</h2>}

看到这个我才真正明白了以前在代码中的RenderBody是如何使用的,布局文件和View是如何结合的。

细节:(可以考虑插入到原有的文章中,这样比较合理哈)

Return View("NotIndex");命名视图

Return View("~/Views/Example/Index.cshtml");

简单请款下推荐使用Dynamic的ViewBag,复杂推荐强类型的ViewModel,在使用强类型时,为了方便,推荐将其加入配置文件中,如下所示。

 <pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="Sory.Entertainment.WebAPI.Models"/>
</namespaces>
</pages>

此外,比较有意思的是,可以通过Install-Package XXX命令安装自己的程序集。

视图模型部分推荐大家使用MVVM模式,尽可能的使数据扁平化,便于强类型的数据管理。

在(设定好Model后)通过基架模板Scaffold template(T4模板)新建视图时,支持Empty、Create、Delete、Details、Edit、List等类型的视图。通过设置RefenceScriptLib添加JQuery(包括非侵入版)验证等相关js。

Razor引擎简单介绍:

通过"@"进行代码和标记的转换符,@@表示原有的@,@(表达式)

表达式 值(只是示例,勿深究)
@ProductList.Length 3
@@ @,转义
Item_@(item.length) Item_3
@{ xxx } 代码块
@{ Html.RenderPartial("SomePartial"); } 代码行
@foreach(var item in items){<span>Item @item.Name</span>} 循环
@if(showMessage){<text>xxx<text>} 判断
@* ………………..*@ 注释,这个需要注意哦,不然可能会出错
@(Html.SomeMethod<Type>) 泛型需要加括号

所有后台数据的呈现默认使用HTML编码(这个html标记类型为System.Web.IHtmlString),如果遇到特殊字符,如<script>alert('hacked!')<alert>等情况,会编码为&lt;script&gt;….,如果需要原样输出,需要使用@Html.Raw(message)。这样就够了么?不然,在前端如果使用js处理后台数据时,为了防止跨站脚本攻击,还需要使用'@Ajax.JavaScriptStringEncode()'防止XSS攻击。

布局,使用在Layout页面中使用@RenderBody可以为主体占位,也可以用的@RenderSection("Footer")为Footer占位,这时需要在页面中通过@section Footer{ html内容 }设置,否则会抛出异常,一个比较合理的例子如下。

 <footer>
@if(IsSectionDefined("Footer")){RenderSection("Footer");}
Else{<span>Default Footer</span>}
</footer>

此外,还可以使用_ViewStart.cshtml页面设置布局页,它可以递归到相应的子目录中,它先于所有页面的渲染。

最后一点是,可以通过部分视图的方式,来满足Ajax调用的需要,这个需要时html文件,而仅仅是json要注意。

 <script>
$(function()){
$('#partialView').Load('/home/partial');
});
</ script >

注:本文主要供自己学习,不妥之处望见谅。

参考资料:

[1]蒋金楠. ASP.NET MVC4框架揭秘[M]. 上海:电子工业出版社, 2012. 390-444

[2](美)加洛韦. ASP.NET MVC 4高级编程(第4版)[M]. 北京:清华大学出版社, 2012.

快速入门系列--MVC--06视图的更多相关文章

  1. 快速入门系列--WebAPI--01基础

    ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因 ...

  2. 快速入门系列--MVC--01概述

    虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入.其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的 ...

  3. 快速入门系列--MVC--02路由

    现在补上URL路由的学习,至于蒋老师自建的MVC小引擎和相关案例就放在论文提交后再实践咯.通过ASP.NET的路由系统,可以完成请求URL与物理文件的分离,其优点是:灵活性.可读性.SEO优化.接下来 ...

  4. 快速入门系列--MVC--07与HTML5移动开发的结合

    现在移动互联网的盛行,跨平台并兼容不同设备的HTML5越来越盛行,很多公司都在将自己过去的非HTML5网站应用渐进式的转化为HTML5应用,使得一套代码可以兼容不同的物理终端设备和浏览器,极大的提高了 ...

  5. [转]快速入门系列--WebAPI--01基础

    本文转自:http://www.cnblogs.com/wanliwang01/p/aspnet_webapi_base01.html ASP.NET MVC和WebAPI已经是.NET Web部分的 ...

  6. 快速入门系列--WebAPI--03框架你值得拥有

    接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...

  7. 快速入门系列--WebAPI--04在老版本MVC4下的调整

    WebAPI是建立在MVC和WCF的基础上的,原来微软老是喜欢封装的很多,这次终于愿意将http编程模型的相关细节暴露给我们了.在之前的介绍中,基本上都基于.NET 4.5之后版本,其System.N ...

  8. vue 快速入门 系列 —— 虚拟 DOM

    其他章节请看: vue 快速入门 系列 虚拟 DOM 什么是虚拟 dom dom 是文档对象模型,以节点树的形式来表现文档. 虚拟 dom 不是真正意义上的 dom.而是一个 javascript 对 ...

  9. vue 快速入门 系列 —— 初步认识 vue

    其他章节请看: vue 快速入门 系列 初步认识 vue vue 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架. 所谓渐进式,就是你可以一步一步.有阶段 ...

  10. vue 快速入门 系列 —— 侦测数据的变化 - [基本实现]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [基本实现] 在 初步认识 vue 这篇文章的 hello-world 示例中,我们通过修改数据(app.seen = false),页面中 ...

随机推荐

  1. Android修改Eclipse 中的Default debug keystore路径,以及修改android的AVD默认路径

    初学android,光是配置Eclipse就走了不少弯路,班里面有很多同学的计算 机名都是写的自己的中文姓名,结果导致了AVD文件默认保存在“C:\user\<username>\.and ...

  2. 【细说Java】关于main方法的一些细节

    Public static void main(String[] args) public :main方法是jvm运行的入口,所以必须是public来供外部调用 static :main方法无需生成对 ...

  3. Python 4 —— 函数与模块

    函数和模块的使用 一.函数 一个例子说明一切. def hello(): print "hello world" def increment(num): num += 1 retu ...

  4. storm trident 示例

    Storm Trident的核心数据模型是一批一批被处理的“流”,“流”在集群的分区在集群的节点上,对“流”的操作也是并行的在每个分区上进行. Trident有五种对“流”的操作: 1.      不 ...

  5. vim指令常用

    慢慢尝试使用vim,不断学习使用新的快捷键,将常用快捷键但经常容易忘的写下来, 1. 复制黏贴 命令行模式下按住v选中,y表示复制,d表示剪切,p为复制.

  6. 51NOD算法马拉松11 B君的竞技场

    传送门 这题我在比赛的时候竟然没有想出来,真是-- 这道题我们可以想一想怎么搞定获胜的概率p. 我们发现再怎么这个p都是搞不了的.所以我们可以积一下分,然后就可以不用去管p了.我们要做的就是求出一个关 ...

  7. javascript练习-方法借用

    方法借用其实也可以叫做多重继承 var generic = { //返回一个字符串,这个字符串包含构造函数的名字(如果构造函数包含名字) //这个以及所有非继承来的,非函数属性的名字和值 toStri ...

  8. c#编程指南(十) 平台调用P-INVOKE完全掌握, 字符串和指针

    可以说新手使用P-INVOKE最开始的头疼就是C#和C++的字符串传递,因为这里涉及到两个问题. 第一:C#的string和C++的字符串首指针如何对应. 第二:字符串还有ANSI和UNICODE(宽 ...

  9. DateTime与DateTime?赋值问题以及null类型的如何赋值问题

    解决方案: //主要用到向下兼容原理,DateTime?继承于DateTime: string req = "为字符串的参数"; DateTime? dt = null; Date ...

  10. kali基本设置

    一.更换比较快的软件源 修改sources.list文件(su): leafpad /etc/apt/sources.list #debain源 deb http://mirrors.163.com/ ...