ASP.NET MVC : 實現我們自己的視圖引擎

來源:互聯網
上載者:User

在ASP.NET MVC的一個開源項目MvcContrib中,為我們提供了幾個視圖引擎,例如NVelocity, Brail, NHaml, XSLT。那麼如果我們想在ASP.NET MVC中實現我們自己的一個視圖引擎,我們應該要怎麼做呢?

我們知道呈現視圖是在Controller中通過傳遞視圖名和資料到RenderView()方法來實現的。好,我們就從這裡下手。我們查看一下ASP.NET MVC的原始碼,看看RenderView()這個方法是如何?的:

protected virtual void RenderView(string viewName, string masterName, object viewData) {           ViewContext viewContext = new ViewContext(ControllerContext, viewName, masterName, viewData, TempData);           ViewEngine.RenderView(viewContext);}//這是P2的源碼,P3略有不同,原理差不多

從上面的代碼我們可以看到,Controller中的RenderView()方法主要是將ControllerContext, viewName, masterName, viewData, TempData這一堆東西封裝成ViewContext,然後把ViewContext傳遞給ViewEngine.RenderView(viewContext)。嗯,沒錯,我們這裡要實現的就是ViewEngine的RenderView()方法。

ASP.NET MVC為我們提供了一個預設的視圖引擎,這個視圖引擎叫做:WebFormsViewEngine. 從名字就可以看出,這個視圖引擎是使用ASP.NET web forms來呈現的。在這裡,我們要實現的視圖引擎所使用的模板用HTML檔案吧,簡單的模板範例程式碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns=""http://www.w3.org/1999/xhtml"">http://www.w3.org/1999/xhtml" ><head>    <title>自訂視圖引擎樣本</title></head><body>    <h1>{$ViewData.Title}</h1>    <p>{$ViewData.Message}</p>    <p>The following fruit is part of a string array: {$ViewData.FruitStrings[1]}</p>    <p>The following fruit is part of an object array: {$ViewData.FruitObjects[1].Name}</p>    <p>Here's an undefined variable: {$UNDEFINED}</p></body></html>

 

下面馬上開始我們的實現。首先,毫無疑問的,我們要建立一個ViewEngine,就命名為 SimpleViewEngine 吧,注意哦,ViewEngine要實現IViewEngine介面:

public class SimpleViewEngine : IViewEngine    {        #region Private members         IViewLocator _viewLocator = null;         #endregion         #region IViewEngine Members : RenderView()         public void RenderView(ViewContext viewContext)        {            string viewLocation = ViewLocator.GetViewLocation(viewContext, viewContext.ViewName);            if (string.IsNullOrEmpty(viewLocation))            {                throw new InvalidOperationException(string.Format("View {0} could not be found.", viewContext.ViewName));            }             string viewPath = viewContext.HttpContext.Request.MapPath(viewLocation);            string viewTemplate = File.ReadAllText(viewPath);             //以下為模板解析            IRenderer renderer = new PrintRenderer();            viewTemplate = renderer.Render(viewTemplate, viewContext);             viewContext.HttpContext.Response.Write(viewTemplate);        }         #endregion         #region Public properties : ViewLocator         public IViewLocator ViewLocator        {            get            {                if (this._viewLocator == null)                {                    this._viewLocator = new SimpleViewLocator();                }                return this._viewLocator;            }            set            {                this._viewLocator = value;            }        }         #endregion    } 

 

在這裡實現了IViewEngine介面提供的RenderView()方法,這裡要提供一個ViewLocator的屬性。ViewLocator的主要就是根據控制器中傳來的視圖名,進行視圖的定位。在RenderView()方法中首先擷取視圖的路徑,然後把視圖模板讀進來,最後進行模板的解析然後輸出。

我們再來看一下ViewLocator是如何?的。他是IViewLocator類型的,也就是說SimpleViewLocator實現了IViewLocator介面。SimpleViewLocator的實現代碼如下:

public class SimpleViewLocator : ViewLocator    {        public SimpleViewLocator()        {            base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.htm",                                                      "~/Views/{1}/{0}.html",                                                      "~/Views/Shared/{0}.htm",                                                      "~/Views/Shared/{0}.html"            };            base.MasterLocationFormats = new string[] { "" };        }    } 

 

我們的SimpleViewLocator 是繼承自ASP.NET MVC的ViewLocator類,而ViewLocator則是實現了IViewLocator介面的。由於ViewLocator已經為了完成了全部的工作,這裡我們只需修改下他的ViewLocationFormats 來使用我們自己的模板檔案就可以了。

我們再來看一下類圖,那就更加清楚了:

註:關於模板解析的部分代碼這裡就不說了,不在討論範圍內,可以自己下載代碼來看

現在我們基本完成了我們的視圖引擎,那麼如何讓ASP.NET MVC不要使用預設的web forms視圖引擎,而使用我們自訂的視圖引擎呢?

在ASP.NET MVC中,所有的請求都是通過一個工廠類來建立Controller執行個體的,這個工廠類必須實現IControllerFactory 介面。預設的實現該介面的工廠類是DefaultControllerFactory。這個工廠類就是我們修改預設的視圖引擎為我們的視圖引擎的進入點。為了方便,我們建立一個繼承自DefaultControllerFactory的SimpleControllerFactory :

public class SimpleControllerFactory : DefaultControllerFactory    {        protected override IController CreateController(RequestContext requestContext, string controllerName)        {            Controller controller = (Controller)base.CreateController(requestContext, controllerName);            controller.ViewEngine = new SimpleViewEngine();//修改預設的視圖引擎為我們剛才建立的視圖引擎            return controller;        }    } 

這裡只要修改controller.ViewEngine為我們自訂的ViewEngine就可以了.最終的類圖大概如下:

要使我們建立的控制器工廠類SimpleControllerFactory 成為預設的控制器工廠類,我們必須在Global.asax.cs中的Application_Start 事件中添加如下代碼:

ControllerBuilder.Current.SetControllerFactory(typeof(SimpleControllerFactory));

到這裡,我們已經完成了我們自己的視圖引擎。

在ASP.NET MVC中實現自訂的視圖引擎是很簡單的,痛點在於模板的解析,具體大家可以研究MvcContrib中的四個視圖引擎的代碼。最近要對模板引擎進行研究,大家有什麼其他優秀的、成熟的、開源的模板引擎,麻煩給小弟推薦一下,先謝了。

Enjoy!

著作權聲明:本文首發於部落格園,作者為QLeelulu
本文著作權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則視為侵權。

參考文章:
ASP.NET MVC Preview生命週期分析
Creating a custom ViewEngine for the ASP.NET MVC framework(下面給出的原始碼就是這篇文章給出的原始碼)

 

本文源碼下載: ASP.NET MVC 自訂視圖引擎原始碼下載

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.