ASP.NET MVC 視圖(二)
前言
上篇中對于視圖引擎隻是做了簡單的示範,對于真正的了解視圖引擎的工作過程可能還有點模糊,本篇将會對由MVC架構提供給我們的Razor視圖引擎的整個執行過程做一個粗略的講解,目的在于讓大家對Razor視圖引擎的執行過程留個印象以便聯想的思考到視圖引擎的作用以及視圖在MVC架構中的表示。
ASP.NETMVC 視圖
l 自定義視圖引擎
l Razor視圖引擎執行過程
l Razor視圖的依賴注入、自定義視圖輔助器
l 分段、分部視圖的使用
l Razor文法、視圖輔助器
Razor視圖引擎執行過程
大家看過上個篇幅對試圖引擎的執行過程有個大概的了解,而Razor視圖引擎的執行則更為詳細,不會像上篇這麼粗糙,來看一下示意圖,圖1.
圖1
<a href="http://s3.51cto.com/wyfs02/M02/3F/FC/wKiom1PNC63SZbqhAAEBnpOMJPc941.jpg" target="_blank"></a>
圖1中所示的是Razor視圖引擎中的對象結構的繼承關系,對于圖1右邊部分的意思則是表示視圖引擎是從系統的ViewEngines.Engines也就是ViewEngineCollection集合類型中取出來的,在ViewEngineCollection下面部分則是表示Razor試圖引擎的一個繼承關系示意圖。
圖2
<a href="http://s3.51cto.com/wyfs02/M01/3F/FD/wKioL1PNDNSjosGWAARAnYFEAHg631.jpg" target="_blank"></a>
我們先來看紅色指針所指部分的流程:
在我們使用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類型來生成視圖處理類,也就是實作了IView的RazorView類型了并且封裝到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
<a href="http://s3.51cto.com/wyfs02/M00/3F/FD/wKioL1PNDPXDAkwCAADsPQ1WLIQ798.jpg" target="_blank"></a>
而對應的視圖代碼【cshtml檔案中的代碼】,如代碼1-1.
代碼1-1
1
2
3
4
5
6
7
8
9
<code>@{</code>
<code> </code><code>ViewBag.Title = "Index";</code>
<code>}</code>
<code> </code>
<code><</code><code>h2</code><code>>Index</</code><code>h2</code><code>></code>
<code>@foreach (varitem in Model)</code>
<code>{</code>
<code> </code><code><</code><code>h3</code><code>>ID: @item.ID Name:@item.Name</</code><code>h3</code><code>></code>
那麼在請求達到控制器過後編譯後的視圖cs檔案存在哪了呢?
在系統的C:\Users\你系統的使用者名\AppData\Local\Temp\Temporary ASP.NET Files中,當然了并不是在這個檔案夾下面,而是在會這裡又生成一些其它的亂七八糟名稱的檔案夾,找一個即可。
我就是在C:\Users\你系統的使用者名\AppData\Local\Temp\Temporary ASP.NETFiles\root\19537580\dfb4a136檔案夾下找的,當然了cs檔案的命名也不是對應着視圖名稱的,一般是由App_Web開頭命名的。經過一番查找找到了對應代碼1-1的cs檔案了,來看一下,代碼1-2
代碼1-2
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<code>#pragma checksum "E:\JY\JY\Action\ASP.NETMVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml""{406ea660-64cf-4c82-b6f0-42d48172a799}""11002EF3288CEAD21A96AC68FD35C045"</code>
<code>//------------------------------------------------------------------------------</code>
<code>//<auto-generated></code>
<code>// 此代碼由工具生成。</code>
<code>// 運作時版本:4.0.30319.1008</code>
<code>//</code>
<code>// 對此檔案的更改可能會導緻不正确的行為,并且如果</code>
<code>// 重新生成代碼,這些更改将會丢失。</code>
<code>//</auto-generated></code>
<code>namespace</code> <code>ASP {</code>
<code> </code><code>usingSystem;</code>
<code> </code><code>usingSystem.Collections.Generic;</code>
<code> </code><code>usingSystem.IO;</code>
<code> </code><code>using</code> <code>System.Linq;</code>
<code> </code><code>usingSystem.Net;</code>
<code> </code><code>usingSystem.Web;</code>
<code> </code><code>usingSystem.Web.Helpers;</code>
<code> </code><code>usingSystem.Web.Security;</code>
<code> </code><code>usingSystem.Web.UI;</code>
<code> </code><code>usingSystem.Web.WebPages;</code>
<code> </code><code>usingSystem.Web.Mvc;</code>
<code> </code><code>usingSystem.Web.Mvc.Ajax;</code>
<code> </code><code>usingSystem.Web.Mvc.Html;</code>
<code> </code><code>usingSystem.Web.Routing;</code>
<code> </code>
<code> </code><code>public</code> <code>class</code> <code>_Page_Views_iocdemo_Index_cshtml: System.Web.Mvc.WebViewPage<dynamic> {</code>
<code> </code>
<code>#line hidden</code>
<code> </code><code>public_Page_Views_iocdemo_Index_cshtml() {</code>
<code> </code><code>}</code>
<code> </code><code>protectedASP.global_asax ApplicationInstance {</code>
<code> </code><code>get</code><code>{</code>
<code> </code><code>return</code><code>((ASP.global_asax)(Context.ApplicationInstance));</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>override</code> <code>voidExecute() {</code>
<code> </code>
<code> </code><code>#line 1 </code><code>"E:\JY\JY\Action\ASP.NETMVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"</code>
<code> </code>
<code> </code><code>ViewBag.Title = </code><code>"Index"</code><code>;</code>
<code> </code><code>#line </code><code>default</code>
<code> </code><code>#line hidden</code>
<code>WriteLiteral(</code><code>"\r\n<h2>Index</h2>\r\n"</code><code>);</code>
<code> </code><code>#line 6 </code><code>"E:\JY\JY\Action\ASP.NETMVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"</code>
<code> </code><code>foreach</code> <code>(</code><code>var</code> <code>item </code><code>in</code> <code>Model)</code>
<code>WriteLiteral(</code><code>" <h3>ID: "</code><code>);</code>
<code> </code><code>#line 8 </code><code>"E:\JY\JY\Action\ASP.NETMVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"</code>
<code> </code><code>Write(item.ID);</code>
<code>WriteLiteral(</code><code>" Name:"</code><code>);</code>
<code> </code><code>Write(item.Name);</code>
<code>WriteLiteral(</code><code>"</h3>\r\n"</code><code>);</code>
<code> </code><code>#line 9 </code><code>"E:\JY\JY\Action\ASP.NETMVC\SystemCase\MyMvcApplication\MvcApplication\Views\iocdemo\Index.cshtml"</code>
<code> </code><code>}</code>
想必看到這裡大家清楚了吧,對于視圖檔案cshtml、vbhtml等等最後在運作時編譯成的類型System.Web.Mvc.WebViewPag,至于類型後面的泛型類型是dynamic類型是對應于普通視圖,而強類型視圖編譯後的類型就會将此處的dynamic類型替換成強類型視圖的ViewModel類型了,最後說一下對于#line的意思可問度娘,是便于我們調試用的。
本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1441082,如需轉載請自行聯系原作者