天天看點

一起談.NET技術,ASP.NET MVC之視圖引擎

  最近微軟釋出了另外一個在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類型的類圖:

一起談.NET技術,ASP.NET MVC之視圖引擎

  這其中用的最多的是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的力量,把資料輸出給使用者。

  它們的關系是:

一起談.NET技術,ASP.NET MVC之視圖引擎

<a href="http://www.51.la/?2866177" target="_blank"></a>

繼續閱讀