最近微軟釋出了另外一個在ASP.NET MVC上應用的視圖引擎Razor。通過前面一系列的探讨,我想大部分都了解了ASP.NET MVC整個的原理,包括TempData、ViewData、ModelBinding、Filter等,但是我們還不是太了解它的視圖引擎的情況。ASP.NET MVC的視圖引擎具有非常好的擴充性,我們可以使用其它的視圖引擎代替WebForm,或是同時使用多種試圖引擎,這些都得益于ASP.NET MVC精美的設計,下面我們一起來觀賞一下它的設計。
<a href="#title1">ActionResult做了什麼?</a>
<a href="#title2">最具代表性的ViewResult</a>
<a href="#title3">ASP.NET MVC的視圖引擎</a>
<a></a>
ActionResult做了什麼?
講到視圖引擎,不得不說ActionResult,因為在Controller中,我們看不到一點視圖引擎的影子,唯一提供線索的隻有ActionResult,是以我們必須先從AcionResult下手。
下面是ASP.NET MVC提供的所有的ActionResult類型的類圖:

這其中用的最多的是ViewResult,ActionResult有一個抽象方法ExecuteResult,這個方法會向使用者的請求中寫入要輸出的内容,比如Response.Write等操作。
最具代表性的ViewResult
在ASP.NET MVC中,ViewResult用的最多,Controller有一個View方法,它來執行個體化一個ViewResult對象,并傳回。下面是View方法:
protected internal virtual ViewResult View(string viewName, string masterName, object model) {
if (model != null) {
ViewData.Model = model;
}
return new ViewResult {
ViewName = viewName,
MasterName = masterName,
ViewData = ViewData,
TempData = TempData
};
它執行個體化一個ViewResult對象,并對其ViewData、TempData指派,以完成從Controller向頁面的傳值。ViewResult繼承自ViewResultBase,ViewResult有一個IView類型的View屬性,IView接口隻有一個方法:
public interface IView {
void Render(ViewContext viewContext, TextWriter writer);
是以,我們推測IView用于輸出内容給使用者。ViewResult類的ExecuteResult方法證明了這一點:
public override void ExecuteResult(ControllerContext context) {
if (context == null) {
throw new ArgumentNullException("context");
if (String.IsNullOrEmpty(ViewName)) {
ViewName = context.RouteData.GetRequiredString("action");
ViewEngineResult result = null;
if (View == null) {
result = FindView(context);
View = result.View;
ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
View.Render(viewContext, context.HttpContext.Response.Output);
if (result != null) {
result.ViewEngine.ReleaseView(context, View);
ASP.NET MVC的視圖引擎
從上一小節中,看到要想得到IView對象,必須先有ViewEngineResult對象,而ViewEngineResult對象是通過ViewResult類的FindView方法得到的:
protected override ViewEngineResult FindView(ControllerContext context) {
ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);
if (result.View != null) {
return result;
// we need to generate an exception containing all the locations we searched
StringBuilder locationsText = new StringBuilder();
foreach (string location in result.SearchedLocations) {
locationsText.AppendLine();
locationsText.Append(location);
throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
MvcResources.Common_ViewNotFound, ViewName, locationsText));
從ViewResult類的FindView方法中,得知ViewEngineResult是通過ViewEngineCollection的FindView得到的,而ViewEngineCollection正是ViewEngines的靜态屬性Engines,Engines傳回一個隻有一個WebFormViewEngine類型執行個體的一個集合。是以,ViewEngineResult會是調用WebFormViewEngine類的FindView方法傳回的結果。如果ViewEngins的靜态屬性Engines有多個ViewEngine提供,那麼就依次周遊它們直到找到第一個不為空的ViewEngineResult為止。這樣我們就可以在同一個MVC網站中使用多種視圖引擎了。
在WebFormViewEngine的FindView方法傳回之前,它會為ViewEngineResult注入一個IView類型的WebFormView執行個體,這樣ViewEngineResult就作為一個中間人把IView類型給ViewResult了,然後ViewResult借助IView的力量,把資料輸出給使用者。
它們的關系是:
<a href="http://www.51.la/?2866177" target="_blank"></a>