ASP.NET MVC 视图(二)

ASP.NET MVC 视图(二)

前言

上篇中对于视图引擎只是做了简单的演示,对于真正的理解视图引擎的工作过程可能还有点模糊,本篇将会对由MVC框架提供给我们的Razor视图引擎的整个执行过程做一个粗略的讲解,目的在于让大家对Razor视图引擎的执行过程留个印象以便联想的思考到视图引擎的作用以及视图在MVC框架中的表示。

 

ASP.NET MVC 视图

  • 自定义视图引擎
  • Razor视图引擎执行过程
  • Razor视图的依赖注入、自定义视图辅助器
  • 分段、分部视图的使用
  • Razor语法、视图辅助器

 

Razor视图引擎执行过程

大家看过上个篇幅对试图引擎的执行过程有个大概的了解,而Razor视图引擎的执行则更为详细,不会像上篇这么粗糙,来看一下示意图,图1.

图1

图1中所示的是Razor视图引擎中的对象结构的继承关系,对于图1右边部分的意思则是表示视图引擎是从系统的ViewEngines.Engines也就是ViewEngineCollection集合类型中取出来的,在ViewEngineCollection下面部分则是表示Razor试图引擎的一个继承关系示意图。

图2

我们先来看红色指针所指部分的流程:

在我们使用ViewResult作为控制器方法的返回类型的时候,MVC框架会首先执行ViewResult中的FindView()方法,而在ViewResult的FindView()中并不是由它自身来执行查找视图的任务的,MVC框架很多管闲事,它会干扰进来。它会从系统的ViewEngines.Engines也就是ViewEngineCollection集合类型中取出来Razor试图引擎来执行查找视图的任务【图1中例举了Razor视图引擎的继承结构】。

随之由VirtualPathProviderViewEngine类型来执行查找视图的任务,实际在这里根据视图名称查找的并不是我们定义的xxxx.cshtml视图文件,而是由xxxx.cshtml文件编译成的cs文件,这些cs文件中表示对应视图的代码,这个在本篇的最后会有讲解,那么这些cs文件是在什么时候生成的呢?是在请求到达控制器的时候,好事的MVC框架就会把View文件夹下或者是对应区域的View文件夹下,关于这个控制器文件夹中的所有视图都会统统的编译生成为cs文件。

扯蛋扯远了回到主题,在VirtualPathProviderViewEngine类型找到视图后【cs文件】,便会让RazorViewEngine类型来生成视图处理类,也就是实现了IViewRazorView类型了并且封装到ViewEngineResult类型实例中。

下面我们就来说明下蓝色指针所指部分的流程:

这个时候MVC框架会调用ViewEngineResult类型中的View属性中的Render()方法,实则就是刚刚上面说的RazorView类型实例中的方法。

然后我们看图2,在Render()方法的执行过程中,首先是由BuildManagerWrapper类型根据视图的路径去读取文件并且动态编译过后返回视图cs文件中所表示的类型,这里BuildManagerWrapper类型是MVC框架的内部类型是实现了内部的IBuildManager接口,BuildManagerWrapper类型的意思就是对于动态编译功能的一个封装,实则就是调用System.Web.Compilation.BuildManager里的功能。

回到主题,类型生成好了过后是由DefaultViewPageActivator类型来生成视图所对应的C#类型【System.Web.Mvc.WebViewPage<dynamic>】,最后通过RazorView类型中的RenderView()方法来对刚刚我们生成好的视图对应的C#类型进行基础性的赋值,比如说从ViewContext类型参数中获取ViewData、ViewBag等等数据信息【ViewContext类型继承自ControllerContext,所以你懂的】进行赋值。

最后会被WebPageRenderingBase类型的对象来做渲染处理,这部分内容就不做阐述了。

以上就是多Razor视图引擎也就是ViewResult类型的处理过程,说的很粗糙大家见谅希望能对大家对于视图的理解上有所帮助。

下面来说一下由MVC框架对于视图文件编译后的cs文件,要眼见为实嘛对吧。

首先我们看一下某个视图的运行的结果,图3.

图3

而对应的视图代码【cshtml文件中的代码】,如代码1-1.

代码1-1

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
@foreach (var item in Model)
{
   <h3>ID: @item.ID Name:@item.Name</h3>
}

那么在请求达到控制器过后编译后的视图cs文件存在哪了呢?

在系统的C:\Users\你系统的用户名\AppData\Local\Temp\Temporary ASP.NET Files中,当然了并不是在这个文件夹下面,而是在会这里又生成一些其它的乱七八糟名称的文件夹,找一个即可。

我就是在C:\Users\你系统的用户名\AppData\Local\Temp\Temporary ASP.NET Files\root\19537580\dfb4a136文件夹下找的,当然了cs文件的命名也不是对应着视图名称的,一般是由App_Web开头命名的。经过一番查找找到了对应代码1-1的cs文件了,来看一下,代码1-2

代码1-2

#pragma checksum "E:\JY\JY\Action\ASP.NET MVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml" "{406ea660-64cf-4c82-b6f0-42d48172a799}" "11002EF3288CEAD21A96AC68FD35C045"
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:4.0.30319.1008
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

namespace ASP {
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Helpers;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.WebPages;
    using System.Web.Mvc;
    using System.Web.Mvc.Ajax;
    using System.Web.Mvc.Html;
    using System.Web.Routing;
    
    
    public class _Page_Views_iocdemo_Index_cshtml : System.Web.Mvc.WebViewPage<dynamic> {
        
#line hidden

        
        public _Page_Views_iocdemo_Index_cshtml() {
        }
        
        protected ASP.global_asax ApplicationInstance {
            get {
                return ((ASP.global_asax)(Context.ApplicationInstance));
            }
        }
        
        public override void Execute() {

            
            #line 1 "E:\JY\JY\Action\ASP.NET MVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"
  
    ViewBag.Title = "Index";


            
            #line default
            #line hidden
WriteLiteral("\r\n<h2>Index</h2>\r\n");


            
            #line 6 "E:\JY\JY\Action\ASP.NET MVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"
 foreach (var item in Model)
{

            
            #line default
            #line hidden
WriteLiteral("   <h3>ID: ");


            
            #line 8 "E:\JY\JY\Action\ASP.NET MVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"
      Write(item.ID);

            
            #line default
            #line hidden
WriteLiteral(" Name:");


            
            #line 8 "E:\JY\JY\Action\ASP.NET MVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"
                    Write(item.Name);

            
            #line default
            #line hidden
WriteLiteral("</h3>\r\n");


            
            #line 9 "E:\JY\JY\Action\ASP.NET MVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"
}
            
            #line default
            #line hidden

        }
    }
}

想必看到这里大家清楚了吧,对于视图文件cshtml、vbhtml等等最后在运行时编译成的类型System.Web.Mvc.WebViewPag,至于类型后面的泛型类型是dynamic类型是对应于普通视图,而强类型视图编译后的类型就会将此处的dynamic类型替换成强类型视图的ViewModel类型了,最后说一下对于#line的意思可问度娘,是便于我们调试用的。


作者:金源

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。