ASP.NET MVC學習之視圖篇(1)


一.前言

不知道還有多少讀者從第一篇開始一直學習到如今,筆者也會一直堅持將ASP.NET MVC的學習完美的結束掉,然后開始寫如何配合其他框架使用ASP.NET MVC的隨筆。當然筆者后面的隨筆如果沒有特殊說明使用的都是ASP.NET MVC 4,因為筆者認為只要精通即可。

 

二.正文

 

1.自定義視圖引擎

相信很多人都知道在控制器中一個動作方法返回一個View之后,ASP.NET MVC默認會到Views下對應的控制器名的文件夾下尋找和這個動作方法同名的視圖(如果你指定了視圖名則會按照你指定的視圖名查找)。但是這中間是如何做到的呢?其實多虧ASP.NET MVC的靈活性強的特點,當你返回View之后,控制器會通過一組視圖引擎去查找對應的頁面,如果其中一個視圖引擎返回了符合的視圖則結束查找開始渲染視圖。下面我們就開始分析上面這幾個過程中涉及的接口有哪些。

 

首先是視圖引擎,它要能夠根據要求返回符合的視圖(實現Iview接口),而視圖引擎需要實現IViewEngine接口,IViewEngine接口代碼如下所示

1     public interface IViewEngine
2     {
3         ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
4         ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
5         void ReleaseView(ControllerContext controllerContext, IView view);
6 }

 其中FindView是根據要求返回對應的視圖,其中ControllerContext包含了控制器相關的數據,viewName則是視圖的名稱,useCache表示是否使用緩存,FindPartialView則是查找分布視圖,最后一個ReleaseView則是釋放頁面對象。

 

這里我們可以看到FindPartialViewFindView都要求返回ViewEngineResult類型,而該類的構造函數有以下幾種方式

1 public ViewEngineResult(IEnumerable<string> searchedLocations);
2 public ViewEngineResult(IView view, IViewEngine viewEngine);

其中第一個是當未查找到時返回的,其中參數是表示該引擎查找了哪些路徑,而第二個則是查找成功后返回的其中要求輸入一個實現IView接口的對象,

第二個參數一般都是this,主要是用來最后調用視圖引擎的ReleaseView方法的,到這里我們就要將視角轉向IView接口,以下是該接口的代碼

 

1 public interface IView
2 {
3     void Render(ViewContext viewContext, TextWriter writer);
4 }

 大家可以看到這接口的方法很少,只有一個Render,而這個方法就是負責最后生成頁面html代碼的,我們可以看到第一個參數是ViewContext,這個參數包含了控制器傳遞到視圖中的參數,比如ViewBag,ViewData等,而第二個參數是用來寫入html代碼的。下面我們簡單的舉一個小例子。

 

首先我們創建一個實現IView接口的對象:

 1 namespace MvcStudy.View
 2 {
 3     public class CustomView : IView
 4     {
 5         public void Render(ViewContext viewContext, System.IO.TextWriter writer)
 6         {
 7             writer.Write("from custom view");
 8         }
 9     }
10 }

 

 

這里我們直接輸出了一個字符串。接着我們還要實現IViewEngine接口:

 1 namespace MvcStudy.View
 2 {
 3     public class CustomViewEngine : IViewEngine
 4     {
 5 
 6         public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
 7         {
 8             return new ViewEngineResult(new string[] { "Custom View Engine" });
 9         }
10 
11         public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
12         {
13             if (viewName.Equals("CustomView"))
14             {
15                 return new ViewEngineResult(new CustomView(), this);
16             }
17             return new ViewEngineResult(new string[] { "Custom View Engine" });
18         }
19 
20         public void ReleaseView(ControllerContext controllerContext, IView view)
21         {
22 
23         }
24     }
25 }

 

 這里我們沒有為分布視圖進行查找,而僅僅只是實現了FindView的查找,並且只有視圖名為CutomView時才會返回對應的結果。

完成了上面的操作,最后我們還要將我們的視圖引擎加入到視圖引擎組中,下面我們在Global.asaxApplication_Start中寫入如下代碼

1 ViewEngines.Engines.Add(new CustomViewEngine ());

 

 

然后修改Home控制器中Index動作方法:

 1 namespace MvcStudy.Controllers
 2 {
 3     public class HomeController : Controller
 4     {
 5         public ActionResult Index()
 6         {
 7             return View("CustomView");
 8         }
 9     }
10 }

 最后我們運行該程序。最后我們將會看到頁面輸出了我們之前寫的字符串,到此為止我們就能夠自己創建自己的視圖引擎了。

 

 

2.修改默認的查詢路徑

可能很多人發現ASP.NET MVC自帶的Razor視圖引擎非常好,並不想自己去實現視圖引擎,而只是想修改查詢的路徑,比如把 ~/Views/[ConrollerName]/[ActionName].cshtml改成~/Views/[ControllerName]_[ActionName].cshtml這種形式,當然強大的ASP.NET MVC依然可以辦到,因為Razor視圖引擎的具體實現類是RazorViewEngine,我們可以繼承這個類,並修改ViewLocationFormats屬性,下面我們將上面的那種查詢方式實現,首先我們新建一個CustomRazorViewEngine類,具體代碼如下

 1 namespace MvcStudy.View
 2 {
 3     public class CustomRazorViewEngine : RazorViewEngine
 4     {
 5         public CustomRazorViewEngine()
 6         {
 7             ViewLocationFormats = new string[]{
 8                 "~/Views/{1}_{0}.cshtml",
 9                 "~/Views/Shared/{0}.cshtml"
10             };
11         }
12     }
13 }

 

其中的{0}{1}代表的是視圖名稱和控制器名稱,如果讀者還要修改區域,則{2}代表區域名稱。

 

我們創建好了之后還要加入到視圖引擎中(仍然在Global.asax中寫入的Application_Start事件中寫入):

1 ViewEngines.Engines.Clear();
2 ViewEngines.Engines.Add(new CustomRazorViewEngine());

 

然后修改Home控制器的Index動作方法,將之前的傳入到View中的參數刪除,然后在Views下新建一個Home_Index.cshtml視圖,重新運行改成程序。

 

 

3.視圖中調用我們自己的方法

有時候視圖中一些常用的功能我們都會響應的集中起來,生成一個工具類,但是在視圖中調用的時候總是要寫入整個命名空間十分麻煩,下面我們可以輕松的解決這個問題。

 

首先我們新建一個工具類:

 1 namespace MvcStudy.Utility
 2 {
 3     public static class ShowHead
 4     {
 5         public static String Show()
 6         {
 7             return "<p>this is head</p>";
 8         }
 9     }
10 }

 

 

然后打開~/Views/Home/Index.cshtml視圖,在頂部加上@using MvcStudy.Utility,然后我們就可以在下面寫入@ShowHead.Show()

當然我們也可以在Views下的Web.config中加入這個命名空間:

1       <namespaces>
2         <add namespace="System.Web.Mvc" />
3         <add namespace="System.Web.Mvc.Ajax" />
4         <add namespace="System.Web.Mvc.Html" />
5         <add namespace="System.Web.Optimization"/>
6         <add namespace="System.Web.Routing" />
7         <add namespace="MvcStudy.Utility"/>
8       </namespaces>

 

這樣所有的視圖都可以使用這個工具類了,但是讀者的運行之后顯示的不會是一個p標簽,而是被轉義之后的字符,這個是ASP.NET MVC為了方式XSS而設置了,所以這里還有一個問題要解決就是如何輸出Html標簽,而不會被轉義,這里就需要使用MvcHtmlString類了,下面我們修改我們的工具類:

 1 namespace MvcStudy.Utility
 2 {
 3     public static class ShowHead
 4     {
 5         public static MvcHtmlString Show()
 6         {
 7             return new MvcHtmlString("<p>this is head</p>");
 8         }
 9     }
10 }

我們看到返回的結果類型從String改成了MvcHtmlString,重新運行程序我們可以發現最后的輸出沒有被轉義了。如果你需要直接輸出Modal中的內容,而不想被轉義則需要調用@Html.Raw(Model),這樣就不會被轉義了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM