MVC中的扩展点(七)视图及视图引擎

    我们知道在MVC框架中,最终通过ActionResult来生成应答内容。上一篇中我们介绍了MVC中默认的结果类型,本章我们将详细介绍ViewResult及PartialViewResult,了解MVC是如何通过视图来生成应答内容的。

    MVC默认的视图被称为Web Forms视图引擎,原因在于它的视图文件使用与ASP.NET Web Forms相同的文件类型(.aspx .ascx),并且使用ASP.NET的页面解析器来解释视图文件内容。也在于,我们在编写视图文件时,可以完全像编写aspx页面文件一样,使用智能提示功能及内联代码等。

    与传统ASP.NET页面一样,在运行时内建的页面编译器会将我们的aspx或ascx文件转换为标准的.NET类,假设我们的视图内容为:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
 <div>
 <%=Html.Label("Hello World!") %>
<%
     using (Html.BeginForm())
    {
    }
%>
 </div>
 

 

    页面编译器会将此视图转换为类似以下的类:

public class views_home_index_aspx : ViewPage, IRequiresSessionState, IHttpHandler
 {
    private void @__BuildControlTree(views_home_index_aspx @__ctrl)
    {
        this.InitializeCulture();
        @__ctrl.SetRenderMethodDelegate(new System.Web.UI.RenderMethod(this.@__Render));
    }
 
    private void @__Render(System.Web.UI.HtmlTextWriter @__w, System.Web.UI.Control parameterContainer)
    {
        @__w.Write("\r\n<div>\r\n");
        @__w.Write(Html.Label("Hello World!"));
        @__w.Write("\r\n");
        using (Html.BeginForm())
        {
        }
        @__w.Write("\r\n</div>\r\n");
    }
}
 

 

    根据此类,生成的页面HTML源代码如下:

 
<div>
<label for="Hello World!">Hello World!</label>
<form action="/" method="post"></form>
</div>
 

 

    显然,在转换时,编译器将非代码内容转换为Response.Write(…)的形式,即直接将内容写入Response,将<%=表达式%>转换为Response.Write(表达式)的形式,即将表达式的返回值写入Response,将<%表达式%>中的表达式直接按代码写入,即直接执行代码,不写入Response。

    从技术上讲,ASP.NET中的aspx是通过PageParserFilter抽象类来控制类代码的生成,在MVC中,MVC实现了自己的解析器:ViewTypeParserFilter,通过它控制将视图文件转换为标准的.NET类的行为。MVC不使用ASP.NET默认解析器的原因在于默认的解析器不支持泛型,即aspx不能从泛型基类中继承,而ViewTypeParserFilter解除了此限制。当我们生成一个MVC项目后,在Views目录下包含了一个Web.config配置文件,从中可以看到MVC已经通过pages的pageParserFilterType项将此目录下的默认页面解析器指定为ViewTypeParserFilter。

    另外,视图文件与传统的aspx页面文件的一种重要不同点在于,传统页面从Page类继承,而视图是从MVC框架中的ViewPage类继承,本质上ViewPage从Page继承,并在Page类基础针对MVC进行了扩展,这也是我们为什么可以在视图中使用模型对象、Html、Ajax等辅助类的原因:

ViewPage

    ViewPage<TModel>是ViewPage的泛型,在创建视图时,通过指定TModel的类型,从而实现强类型的ViewPage。

MVC视图引擎架构

    视图引擎的执行方式很简单:通过ViewEngines.FindView根据当前的ControllerContext找出适当的视图引擎及视图,然后调用视图的Render方法生成应答内容,最后通过视图引擎的ReleaseView方法是否视图资源:

ViewActivity

    MVC默认的Web Forms视图引擎类图如下:

ViewClass

    IView、IViewEngine、ViewEngineResult是视图引擎的核心,IView接口负责视图的渲染,IViewEngine负责找出合适的视图文件,ViewEngineResult是对IView和IViewEngine的封装。

    ViewEngineCollection表示一个IViewEngine集合,MVC提供向集合添加视图引擎的方法,并提供FindView、FindPartialView方法,从集合项中找出与当前ControllerContext匹配的ViewEngineResult。

    ViewEngines是一个静态类,其内部封装了一个ViewEngineCollection,构成了MVC框架默认的视图引擎集合,默认下,该结合仅包含一个Web Forms引擎。我们可通过视图引擎集合上的方法向其添加自定义的视图引擎。

    WebFormViewEngine是IViewEngine的一个实现,表示一个Web Forms视图引擎。

    WebFormView是IView的一个实现,表示一个Web Forms视图,其内部Render方法,将实例化一个通过视图aspx文件转换而来的类型。通过该类型将试图文件渲染为最终的应答结果。

第三方视图引擎

    MVC视图引擎有不少开源项目,比较完善的有以下几种:

1、Spark View Engine:

    官网:http://sparkviewengine.com/ 下载:http://sparkviewengine.codeplex.com/

2、NHaml View Engine

    官网:http://code.google.com/p/nhaml/  下载:http://code.google.com/p/nhaml/downloads/list

3、Razor:

    此引擎有MVC同一团队开发,官网:http://www.asp.net/mvc  或者 http://www.asp.net/WebMatrix

    每一个视图引擎都有自己不同的语法规则,对此本文不做介绍,请参考官方文档。另外,关于这几个引擎的粗略介绍,可参考以下博客:http://blogs.msdn.com/b/coding4fun/archive/2010/10/04/10070953.aspx

    下面以Spark视图引擎为例,简要介绍第三方视图引擎的使用步骤:

1、下载Spark视图引擎并解压

2、新建一空的MVC项目,并添加对Spark.dll及Spark.Web.Mvc.dll的引用

3、修改Global.asax.cs,在Application_Start过程中想默认视图引擎集合中添加Spark视图引擎

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Add(new SparkViewFactory());
}
 

4、添加一个HomeController:

显示行号 复制代码 HomeController
  1. public class HomeController : Controller
    
  2.  {
    
  3.     private List<Product> products = new List<Product>()
    
  4.     {
    
  5.         new Product(){ID="0001", Name = "测a试?产ú品·1", Price=1},
    
  6.         new Product(){ID="0002", Name = "测a试?产ú品·2", Price=1}
    
  7.     };
    
  8. 
    
  9.     public ActionResult Index()
    
  10.     {
    
  11.         ViewData["products"] = products;
    
  12.         return View();
    
  13.     }
    
  14. 
    
  15. }
    
  16. 
    

5、在Models下建立一个Product类

显示行号 复制代码 Product
  1. public class Product
    
  2. {
    
  3.     public string ID { get; set; }
    
  4.     public string Name { get; set; }
    
  5.     public string Description { get; set; }
    
  6.     public decimal Price { get; set; }
    
  7. }
    
  8. 
    


6、修改web.config,在configSections下添加spark配置节:

<section name="spark" type="Spark.Configuration.SparkSectionHandler, Spark"/>


7、在web.config中配置spark(如默认的命名空间引用):

  <spark>
    <compilation debug="true" defaultLanguage="CSharp" />
    <pages automaticEncoding="true" >
      <namespaces>
        <add namespace="System"/>
        <add namespace="System.Collections.Generic"/>
        <add namespace="System.Linq"/>
        <add namespace="System.Web"/>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Html"/>
      </namespaces>
    </pages>
  </spark>

8、在Views下创建Home目录,并在此目录下添加Index.spark视图模板文件:
<viewdata products="IList[[Models.Product]]"/>
<div each="var product in products">
    <h2>${product.Name}</h2>
</div>

 

    说明:本例仅演示如何使用第三方视图引擎,如果想详细了解Spark视图引擎,请访问官方网站。

    源代码下载

posted @ 2011-01-10 20:01  xfrog  阅读(6424)  评论(7编辑  收藏  举报