<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      從零開始學(xué)習(xí) ASP.NET MVC 1.0 (五) ViewEngine 深入解析與應(yīng)用實(shí)例

      《從零開始學(xué)習(xí)ASP.NET MVC 1.0》 文章導(dǎo)航

       

      一.摘要

      本文講解ViewEngine的作用, 并且深入解析了實(shí)現(xiàn)ViewEngine相關(guān)的所有接口和類, 最后演示了如何開發(fā)一個(gè)自定義的ViewEngine. 本系列文章已經(jīng)全部更新為ASP.NET MVC 1.0版本.希望大家多多支持!

      二.承上啟下

      首先注意: 我會(huì)將大家在MVC之前一直使用的ASP.NET頁面編程模型稱作ASP.NET WebForm編程模型.

      上一講中我們已經(jīng)學(xué)習(xí)了如何向View傳遞Model, 以及如何在View中使用Model對象. 目前為止我們使用的都還是ASP.NET WebForm的頁面模型,比如aspx頁面,用戶控件,母版頁等. 最后這些頁面中都要轉(zhuǎn)換為HTML代碼. 比如頁面中的內(nèi)嵌代碼:

      <% = ViewData["model"] %>

      你是否思考過, 為何頁面會(huì)支持<% %>這種語法? 為何最后一個(gè)aspx頁面會(huì)在瀏覽器中以HTML代碼的形式展現(xiàn)?

      有人會(huì)回答這是ASP.NET自帶的語法和功能. 沒有錯(cuò), ASP.NET幫我們做了編譯頁面, 輸出HTML, 返回HTML給客戶端瀏覽器等一系列工作.但是這些工作在MVC框架中有很多是屬于View角色的職責(zé). 為了繼續(xù)使用原有的ASP.NET WebForm頁面引擎, ASP.NET MVC抽象出來了ViewEngine這個(gè)角色. 顧名思義ViewEngine即視圖引擎, 其主要作用就是找到View對象,  編譯View對象中的語言代碼(執(zhí)行語言邏輯), 并且輸出HTML. 下面講解的WebFormViewEngine就是使用ASP.NET WebForm的頁面編譯/呈現(xiàn)功能實(shí)現(xiàn)的.

      三.ViewEngine解析

      下面將講解和ViewEngine有關(guān)的各個(gè)接口和類.

      IView接口

      IView接口是對MVC結(jié)構(gòu)中View對象的抽象, 此接口只有一個(gè)方法:

      void Render(ViewContext viewContext, TextWriter writer);


      Render方法的作用就是展示View對象, 通常是將頁面HTML寫入到Writer中供瀏覽器展示.

      在本系列第三篇文章中我曾經(jīng)分析過, 雖然IView對象是MVC中View角色的抽象, 并且提供了Render方法, 但是實(shí)際上真正的View角色的顯示邏輯在ViewPage/ViewUserControl類中. 這是由于ASP.NET MVC提供的WebFormViewEngine視圖引擎是使用原有的ASP.NET Web From的頁面顯示機(jī)制, 我們無法直接將WebForm模型中的頁面轉(zhuǎn)化為IView對象.

      于是最后使用了一個(gè)折中的辦法:

      在IView對象的Render方法中調(diào)用WebForm頁面的Render方法. WebFormView是目前ASP.NET MVC中唯一實(shí)現(xiàn)了IView接口的類

      所以如果我們使用自定義的ViewEngine引擎, 就可以直接創(chuàng)建一個(gè)實(shí)現(xiàn)了IView接口的類實(shí)現(xiàn)Render方法.

       

      IViewEngine接口

      ViewEngine即視圖引擎, 在ASP.NET MVC中將ViewEngine的作用抽象成了 IViewEngine 接口.

      雖然IViewEngine的職責(zé)是尋找View對象, 但是其定義的兩個(gè)方法:

      • FindPartialView
      • FindView

      返回的結(jié)果是ViewEngineResult對象, 并不是View對象. 我們可以將ViewEngineResult理解為一次查詢的結(jié)果, 在ViewEngineResult對象中包含有本次找到的IView對象.

      ASP.NET MVC 提供了下面兩個(gè)實(shí)現(xiàn)了IViewEngine接口的類:

      • VirtualPathProviderViewEngine
      • WebFormViewEngine

      WebFormViewEngine是VirtualPathProviderViewEngine的派生類.

      VirtualPathProviderViewEngine類實(shí)現(xiàn)了FindPartialView/FindView方法, 更夠根據(jù)指定的路徑格式搜索頁面文件, 并且使用了提供了Cache機(jī)制緩存數(shù)據(jù). 注意因?yàn)槭褂玫氖茿SP.NET Cache,依賴HttpContext對象, 這就導(dǎo)致Cache無法在WebService或者WCf等項(xiàng)目中使用. VirtualPathProviderViewEngine尋找頁面的方法依賴下面三個(gè)屬性:

      • MasterLocationFormats
      • ViewLocationFormats
      • PartialViewLocationFormats

      在VirtualPathProviderViewEngine中只定義了這三個(gè)屬性, 具體的值在派生類WebFormViewEngine中指定:

              public WebFormViewEngine() {
                  MasterLocationFormats = new[] {
                      "~/Views/{1}/{0}.master",
                      "~/Views/Shared/{0}.master"
                  };
      
                  ViewLocationFormats = new[] {
                      "~/Views/{1}/{0}.aspx",
                      "~/Views/{1}/{0}.ascx",
                      "~/Views/Shared/{0}.aspx",
                      "~/Views/Shared/{0}.ascx"
                  };
      
                  PartialViewLocationFormats = ViewLocationFormats;
              }

      上面的代碼中我們可以一步了然ViewEngine都搜索哪些路徑.甚至還可以添加我們自己的路徑和文件類型.

      因?yàn)橛辛薞irtualPathProviderViewEngine類, 在開發(fā)自定義的ViewEngine時(shí)不需要再編寫搜索View文件的邏輯了.只需要定義搜索路徑即可. 如果不使用ASP.NET WebForm的頁面顯示方式, 就需要自己定義的View對象如何顯最后轉(zhuǎn)化為HTML代碼.

      在后面的實(shí)例中會(huì)演示創(chuàng)建一個(gè)我們自定義的ViewEngine.

       

      ViewEngineResult

      ViewEngineResult是ViewEngine尋找View的查詢結(jié)果.ViewEngineResult類沒有派生類,  也就是說不同的ViewEngine返回的結(jié)果都是ViewEngineResult對象.

      ViewEngineResult類有一個(gè)很重要的構(gòu)造函數(shù):

      public ViewEngineResult(IView view, IViewEngine viewEngine)

       

      以WebFormViewEngine為例, 在WebFormViewEngine類中定義了 MasterLocationFormats/ViewLocationFormats /PartialViewLocationFormats , 在調(diào)用FindPartialView/FindView方法時(shí), 首先找到View對象的磁盤路徑, 然后使用CreatePartialView/CreateView方法將磁盤路徑轉(zhuǎn)化實(shí)現(xiàn)了IView接口的WebFormView對象.

      WebFormView中依然保存這頁面對象的磁盤路徑, 在調(diào)用Render時(shí)會(huì)根據(jù)磁盤路徑創(chuàng)建ViewPage對象, 調(diào)用頁面的Render方法.ASP.NET MVC編譯頁面時(shí), 使用了.NET Framework 2.0以上的版本中提供的根據(jù)虛擬路徑編譯頁面的函數(shù):

      BuildManager.CreateInstanceFromVirtualPath(string virtualPath, Type requiredBaseType)

      命名空間為System.Web.Compilation.

       

      ViewEngineCollection

      ViewEngineCollection是IViewEngine對象的集合類. 在我們的系統(tǒng)中可以使用多個(gè)ViewEngine,  在尋找時(shí)會(huì)返回第一個(gè)匹配的ViewEngineResult, 下面是ViewEngineCollection類的Find方法代碼:

              private ViewEngineResult Find(Func<IViewEngine, ViewEngineResult> cacheLocator, Func<IViewEngine, ViewEngineResult> locator) {
                  ViewEngineResult result;
      
                  foreach (IViewEngine engine in Items) {
                      if (engine != null) {
                          result = cacheLocator(engine);
      
                          if (result.View != null) {
                              return result;
                          }
                      }
                  }
      
                  List<string> searched = new List<string>();
      
                  foreach (IViewEngine engine in Items) {
                      if (engine != null) {
                          result = locator(engine);
      
                          if (result.View != null) {
                              return result;
                          }
      
                          searched.AddRange(result.SearchedLocations);
                      }
                  }
      
                  return new ViewEngineResult(searched);
              }

      通過上面的代碼我們了解到, ViewEngineCollection會(huì)首先從Cache中搜索, 如果沒有搜索到結(jié)果,則根據(jù)路徑格式搜索. 如果最后還是沒有搜索到View對象則拋出找不到View的異常.所以雖然我們可以添加多個(gè)ViewEngine, 但是永遠(yuǎn)不要為兩個(gè)ViewEngine指定同樣的搜索格式(路徑+文件類型), 因?yàn)槿绻霈F(xiàn)一個(gè)頁面對象符合兩個(gè)ViewEngine的搜索格式的情況, 將無法控制使用哪一個(gè)ViewEngine輸出頁面.

      ViewBaseResult.ExecuteResult() 方法中, 調(diào)用了ViewEngineCollection.Find方法獲取ViewEngineResult對象,并調(diào)用其中的IView.Render()方法完成View對象的顯示.

      四.開發(fā)自定義ViewEngine

      下面通過示例演示如何開發(fā)自己的ViewEngine.其中要用到StringTemplate這個(gè)模板引擎, 在老趙的的MVC視頻教程中也使用的此引擎演示ViewEngine. StringTemplate負(fù)責(zé)翻譯一個(gè)模板頁上面的占位符(aspx頁面中的內(nèi)嵌代碼), 輸出HTML.目前在StringTemplate的官方網(wǎng)站上已經(jīng)提供了針對Asp.Net Mvc的ViewEngine.但是官方的ViewEngine模板沒有使用VirtualPathProviderViewEngine基類.下面我將提供一種不能說更好但至少是另一種實(shí)現(xiàn)的StringTemplateViewEngine.其中需要使用StringTemplate的模版功能.

      1. 實(shí)現(xiàn)IView接口

      要開發(fā)一個(gè)自己的ViewEngine, 首先要?jiǎng)?chuàng)建實(shí)現(xiàn)了IView接口的類, 在此我們創(chuàng)建了名為StringTemplateView的類

      public class StringTemplateView : IView
          {
              #region 屬性 Properties
              /// <summary>
              /// StringTemplate 對象, 在構(gòu)造函數(shù)中創(chuàng)建
              /// </summary>
              private StringTemplate StringTemplate 
              { 
                  get; set; 
              }
              #endregion
      
              #region 構(gòu)造函數(shù) Constructed Function 
              private StringTemplateView()
              {
                  //不用于使用不帶參數(shù)的構(gòu)造函數(shù)
                  this.StringTemplate = new StringTemplate();
              }
      
              public StringTemplateView(StringTemplate template)
              {
                  //null check
                  if (template == null) throw new ArgumentNullException("template");
      
                  //set template
                  this.StringTemplate = template;
              }
              #endregion
      
              #region IView 成員
      
              void IView.Render(ViewContext viewContext, System.IO.TextWriter writer)
              {
                  foreach(var item in viewContext.ViewData)
                  {
                      this.StringTemplate.SetAttribute(item.Key.ToString(), item.Value.ToString());
                  }
      
                  //為StringTemplate設(shè)置HttpContext
                  this.StringTemplate.SetAttribute("context", viewContext.HttpContext);
      
                  //輸出模板
                  NoIndentWriter noIndentWriter = new NoIndentWriter(writer);
                  this.StringTemplate.Write(noIndentWriter);
      
              }
      
              #endregion
          }

      StringTemplateView是在StringTemplate視圖引擎中View角色的抽象, 所以功能是實(shí)現(xiàn)呈現(xiàn)頁面的Render方法. StringTemplate的核心功能就是一套自己定義的模板輸出引擎, 所以在構(gòu)造StringTemplateView對象是必須傳入一個(gè)StringTemplate實(shí)例,在Render時(shí)只是調(diào)用StringTemplate對象的模板輸出方法.

      2. 實(shí)現(xiàn)IViewEngine接口

      有了IView對象. 接下來就要實(shí)現(xiàn)最核心的IViewEngine接口. 在具體的StringTemplateViewEngine類中, 要返回一個(gè)帶有StringTemplateView對象的ViewEngineResult.

      在我的實(shí)現(xiàn)方法中,使用了ASP.NET MVC已經(jīng)提供的VirtualPathProviderViewEngine類作為我們的基類. VirtualPathProviderViewEngine類實(shí)現(xiàn)了IViewEngine接口的方法, 提供了在程序中尋找View物理文件路徑的機(jī)制, 搜索時(shí)要使用在派生類中賦值的搜索路徑.

      下面是我們的StringTemplateViewEngine類實(shí)現(xiàn):

          public class StringTemplateViewEngine : VirtualPathProviderViewEngine
          {
              private string _AppPath = string.Empty;
      
              #region 屬性 Properties
              public static FileSystemTemplateLoader Loader { get; private set; }
              public static StringTemplateGroup Group { get; private set; }
              #endregion
      
              public StringTemplateViewEngine(string appPath)
              {
                  _AppPath = appPath;
                  Loader = new FileSystemTemplateLoader(appPath);
                  Group = new StringTemplateGroup("views", Loader);
      
                  MasterLocationFormats = new[] {
                      "/Views/{1}/{0}.st",
                      "/Views//Shared/{0}.st" 
                  };
      
                  ViewLocationFormats = MasterLocationFormats;
      
                  PartialViewLocationFormats = MasterLocationFormats;
              }
      
              protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
              {
                  return this.CreateView(controllerContext, partialPath, String.Empty);
              }
      
              protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
              {            
      
                  StringTemplate stringTemplate = Group.GetInstanceOf(viewPath.Replace(".st", ""));
                  StringTemplateView result = new StringTemplateView(stringTemplate);
                  return result;
              }
          }

      注意首先在我們的StringTemplateViewEngine中,提供了搜索模板文件的路徑,即先從View/{controller}中搜索,再從View/Share中搜索. 這樣VirtualPathProviderViewEngine基類的方法就可以找到我們.st模板文件的具體路徑, 然后使用StringTemplateViewEngine中提供的創(chuàng)建StringTemplateView的方法, 根據(jù)具體路徑創(chuàng)建StringTemplateView對象.

      在一些開源的ViewEngine中,尤其是MvcContrib項(xiàng)目中的ViewEngine都將創(chuàng)建View對象的功能放在一個(gè)ViewFactory類中, 個(gè)人認(rèn)為這個(gè)更好的設(shè)計(jì), 但是由于我們的StringTemplateViewEngine要繼承VirtualPathProviderViewEngine, 所以沒辦法拆分創(chuàng)建View的方法.

      至此我們已經(jīng)完成了StringTemplateViewEngine的全部工作.

      3.使用StringTemplateViewEngine

      (1)為 .st 模板頁增加智能感知

      首先做一些準(zhǔn)備工作. 因?yàn)槲覀兊腟tringTemplate模板文件后綴是".st", 里面寫的大部分都是HTML代碼. 默認(rèn)情況下Visual Studio是不會(huì)在編輯.st功能的時(shí)候提供智能感知支持的. 但是可以通過如下設(shè)置實(shí)現(xiàn):

      單擊菜單中的"工具"->"選項(xiàng)":

      image

      在"文本編輯器"的文件擴(kuò)展名中, 如圖所示的為.st擴(kuò)展名增加"HTML編輯器".

      接下來在.st文件中就可以識(shí)別HTML代碼了:

      image 

      (2) 創(chuàng)建公用的菜單模板

      StringTemplate引擎支持模板的嵌套, 所以可以講兩個(gè)頁面公用的菜單欄放在menu.st文件中. 而且我們將此文件放在share文件夾中以便供所有模板頁調(diào)用. menu.st文件代碼如下:

      <ul id="menu">
          <li><a href="/StringTemplate/HelloST">HelloST</a></li>
          <li><a href="/StringTemplate/SharedST">SharedST</a></li>
      </ul> 

      (3) 創(chuàng)建頁面模板和Controller

      在Controller文件夾中, 創(chuàng)建StringTemplateController用于跳轉(zhuǎn)到我們的模板頁:

          public class StringTemplateController : Controller
          {
              public ActionResult HelloST()
              {
                  ViewData["msg"] = "Hello String Template ! ";
                  return View("HelloST");
              }
          }

      在View文件夾中創(chuàng)建StringTemplate文件夾, 添加一個(gè)HelloST.st文件:

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
      <title>在Shared文件夾中的st頁面</title>
      <link href="../Content/Site.css" rel="stylesheet" type="text/css" /></head>
      <body>
          <div class="page">  
              <h1>StringTemplateViewEngine示例程序</h1>
              <div id="menucontainer"> 
                  $Views/Shared/menu()$
              </div>
              
              <div id="main">
                  $msg$
              </div>
          </div>
      </body>
      </html>

      示例中的代碼十分簡單, "$msg$"是StringTemplate的模板語言, 可以識(shí)別名稱為"msg"的變量. "$Views/Shared/menu()$"也是StringTemplate中的語法, 作用是加載名為menu的模板.

      (4) 加載StringTemplateViewEngine 模板引擎

      雖然Controller和View文件都建立好了, 但是因?yàn)锳SP.NET MVC默認(rèn)的視圖引擎是WebFormViewEngine, 但是可以同時(shí)使用多個(gè)視圖引擎, 比如可以為所有".st"后綴名的文件使用StringTemplateViewEngine視圖引擎.在Global.asax文件中, 在程序啟動(dòng)時(shí)注冊我們的ViewEngine:

              protected void Application_Start()
              {
                  RegisterRoutes(RouteTable.Routes);
      
                  //添加StringTemplate視圖引擎
                  StringTemplateViewEngine engine = new StringTemplateViewEngine(Server.MapPath("/"));
                  ViewEngines.Engines.Add(engine);
              }

      現(xiàn)在, 訪問"localhost/StringTemplate/HelloST",就可以看到我們的自定義的模板引擎的輸出結(jié)果了:

      image

      在文章最后會(huì)提供本實(shí)例附帶StringTemplateViewEngine的完整源代碼.

       

      五.其他ViewEngine簡介

      除了自己開發(fā), 目前已經(jīng)有了很多為ASP.NET MVC提供的ViewEngine:

      MVCContrib項(xiàng)目中的ViewEngine:

      • SparkViewEngine(不推薦)
      • BrailViewEngine
      • XsltViewEngine

      StringTemplateViewEngine

      這是StringTemplate項(xiàng)目為ASP.NET MVC開發(fā)的ViewEngine, 官方以及下載網(wǎng)址是

      http://www.stringtemplate.org/

      另外在著名的MonoRail項(xiàng)目中, 還有一些類似于StringTemplate的頁面顯示引擎, 雖然都沒有為ASP.NET MVC開發(fā)專門的ViewEngine, 但是還是很有參考價(jià)值的.我們可以用上面介紹的方法, 在頁面顯示引擎的基礎(chǔ)上自己開發(fā)ASP.NET MVC的ViewEngine:

      MonoRail項(xiàng)目中的三個(gè)ViewEngine:

      • AspNetViewEngine:用傳統(tǒng)的.aspx文件做模板, 可以照常使用aspx語法和服務(wù)器控件, 但是由于Webform的生命周期和MonoRail完全不同, 有時(shí)候會(huì)讓人覺得別扭, 有部分特性也受到了限制.
      • NVelocityViewEngine: 用NVelocity做模板引擎, 需要學(xué)習(xí)VTL語法, 但是使用很簡單, 特別是很多java程序員已經(jīng)熟悉velocity. 簡單的語法也強(qiáng)迫程序員把邏輯和界面很好的分離開來, 方便跟美工配合.
      • BrailViewEngine:基于Boo的模板引擎, Boo是一種語法類似python的.NET語言, 據(jù)MonoRail的參考說, Brail引擎是功能最強(qiáng), 性能最好的選擇, 但Boo是一種陌生的語言, 這成了Brail引擎應(yīng)用的最大障礙.

      六.總結(jié)

      本篇文章詳細(xì)介紹了ViewEngine相關(guān)類, 已經(jīng)如何開發(fā)自己的ViewEngine. 花了2周時(shí)間創(chuàng)作完成, 讓大家久等了. 說道最近博客園首頁的文章問題, 我覺得一篇文章除了要有知識(shí)點(diǎn), 還有能夠很好的講解, 讓大家明白比讓自己明白更重要.我沒有為了速度草草發(fā)表文章,就是希望寫出來的東西能夠有資格發(fā)表到博客園首頁.

      我希望大家都通過自律來建設(shè)博客園,  明白分享知識(shí)是一件光榮而且快樂的事情!

      文章示例代碼下載:

      https://files.cnblogs.com/zhangziqiu/AspNetMvc-5-Demo.rar

      posted @ 2009-03-22 14:39  ziqiu.zhang  閱讀(34165)  評(píng)論(59)    收藏  舉報(bào)
      主站蜘蛛池模板: 人妻丝袜中文无码av影音先锋 | 超碰成人人人做人人爽| 精品视频一区二区| 泾阳县| 婷婷综合亚洲| 五月天国产成人av免费观看| 国产一卡2卡三卡4卡免费网站| 精品福利一区二区三区免费视频| 狠狠色综合久久狠狠色综合| 成人精品区| 久久久久久久波多野结衣高潮| 免费人妻无码不卡中文字幕系| 国产成人久久综合第一区| 亚洲中文字幕成人综合网| 午夜成人精品福利网站在线观看| 国产一二三五区不在卡| 丰满人妻被黑人猛烈进入| 免费看无码自慰一区二区| 亚洲日韩一区二区| 日本熟妇人妻一区二区三区| 国产无遮挡又黄又爽不要vip软件 国产成人精品一区二区秒拍1o | 久久99热成人精品国产| 亚洲性日韩精品一区二区三区| 久久国产av影片| 大尺度国产一区二区视频| 亚洲乱理伦片在线观看中字| 婷婷四房综合激情五月在线| 中文字幕无码av不卡一区| 18禁在线一区二区三区| 亚洲乱亚洲乱妇50p| 国内精品免费久久久久电影院97| 国产精品国产高清国产一区| 资源在线观看视频一区二区| 性一交一乱一乱一视频| 亚洲国产一区二区三区四| 中文字幕免费不卡二区| 7878成人国产在线观看| 狠狠久久五月综合色和啪| 9191国语精品高清在线| 亚洲午夜无码久久久久蜜臀av | 一区二区三区精品偷拍|