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

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

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

      自己動手寫一個簡單的MVC框架(第二版)

      一、ASP.NET MVC核心機制回顧

        在ASP.NET MVC中,最核心的當屬“路由系統”,而路由系統的核心則源于一個強大的System.Web.Routing.dll組件。

        在這個System.Web.Routing.dll中,有一個最重要的類叫做UrlRoutingModule,它是一個實現了IHttpModule接口的類,在請求處理管道中專門針對ASP.NET MVC請求進行處理。首先,我們要了解一下UrlRoutingModule是如何起作用的。

        (1)IIS網站的配置可以分為兩個塊:全局 Web.config 和本站 Web.config。Asp.Net Routing屬于全局性的,所以它配置在全局Web.Config 中,我們可以在如下路徑中找到:“$\Windows\Microsoft.NET\Framework\版本號\Config\Web.config“

       <?xml version="1.0" encoding="utf-8"?>
       <!-- the root web configuration file -->
       <configuration>
           <system.web>
               <httpModules>
                   <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
               </httpModules>
          </system.web>
       </configuration>

        (2)通過在全局Web.Config中注冊 System.Web.Routing.UrlRoutingModule,IIS請求處理管道接到請求后,就會加載 UrlRoutingModule類型的Init()方法。

      PS : 在UrlRoutingModule中為請求處理管道中的第七個事件PostResolveRequestCache注冊了一個事件處理方法:OnApplicationPostResolveRequestCache。從這里可以看出:ASP.NET MVC的入口在UrlRoutingModule,即訂閱了HttpApplication的第7個管道事件PostResolveRequestCahce。換句話說,是在HtttpApplication的第7個管道事件處對請求進行了攔截

        現在我們將ASP.NET MVC的請求處理分為兩個重要階段來看看:

       ①在第七個事件中創建實現了IHttpHandler接口的MvcHandler

        當請求到達UrlRoutingModule的時候,UrlRoutingModule取出請求中的Controller、Action等RouteData信息,與路由表中的所有規則進行匹配,若匹配,把請求交給IRouteHandler,即MVCRouteHandler。我們可以看下UrlRoutingModule的源碼來看看,以下是幾句核心的代碼:

      public virtual void PostResolveRequestCache(HttpContextBase context)
      {
          // 通過RouteCollection的靜態方法GetRouteData獲取到封裝路由信息的RouteData實例
          RouteData routeData = this.RouteCollection.GetRouteData(context);
          if (routeData != null)
          {
              // 再從RouteData中獲取MVCRouteHandler
              IRouteHandler routeHandler = routeData.RouteHandler;
              ......
              if (!(routeHandler is StopRoutingHandler))
              {
                  ......
                  // 調用 IRouteHandler.GetHttpHandler(),獲取的IHttpHandler 類型實例,它是由 IRouteHandler.GetHttpHandler獲取的,這個得去MVC的源碼里看
                  IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
                  ......
                  // 合適條件下,把之前將獲取的IHttpHandler 類型實例 映射到IIS HTTP處理管道中
                  context.RemapHandler(httpHandler);
              }
          }
      }
      View Code

        從源碼片段中可以看出,最后將請求轉移給了實現了IHttpHandler接口的處理程序進行后續的處理。在ASP.NET MVC的實現中,是將請求交給了MvcHandler這個類,通過執行其ProcessRequest方法來進行后續的處理。

       ②在第十一個事件與第十二個事件之間調用MvcHandler的ProcessRequest()方法

        (1)在WebForm中,此階段會調用Page類對象的ProcessRequest()方法。在ASP.NET MVC中,會調用MvcHandler的ProcessRequest()方法,此方法會激活具體請求的Controller類對象,觸發Action方法,返回ActionResult實例

        (2)如果ActionResult是非ViewResult,比如JsonResult, ContentResult,這些內容將直接被輸送到Response響應流中,顯示給客戶端;如果是ViewResult,就會進入下一個渲染視圖環節。

        (3)在渲染視圖環節,ViewEngine找到需要被渲染的視圖,View被加載成WebViewPage<TModel>類型,并渲染生成Html,最終返回Html。

      二、我的MVC框架核心部分介紹

      2.1 解決方案概覽

        在該解決方案中,一共有兩個項目:

        一個是App,它是一個由最小化的引用環境(只引用了System和System.Web,以及Mvc.Lib)搭建起來的一個Web應用項目,借助MVC核心類庫(Mvc.Lib)實現了MVC模式。

        一個是Lib,它是一個模擬ASP.NET MVC框架的最小化、輕量級的迷你MVC框架,其中Mvc文件夾模擬System.Web.Mvc,Routing文件夾模擬System.Web.Routing,而View則簡單地借助NVelocity模板引擎提供View視圖服務。

      2.2 MVC核心類庫

        (1)Routing

        

        從第一部分我們可以知道,ASP.NET MVC的入口在于UrlRoutingModule,因此這里我們便模擬實現了一個UrlRoutingModule.

          /// <summary>
          /// 解析請求中的路由數據,并分發請求到Handler
          /// </summary>
          public class UrlRoutingModule : IHttpModule
          {
              public void Init(HttpApplication application)
              {
                  // 注冊ASP.NET請求處理管道的第七個事件
                  application.PostResolveRequestCache += Application_PostResolveRequestCache;
              }
      
              // 假設請求 http://www.edisonchou.cn/home/index
              private void Application_PostResolveRequestCache(object sender, EventArgs e)
              {
                  var application = sender as HttpApplication;
                  var context = application.Context;
                  // 根據全局路由表解析當前請求的路徑
                  var requestUrl = context.Request.AppRelativeCurrentExecutionFilePath.Substring(2);
                  // 遍歷全局路由表中的路由規則解析數據
                  IDictionary<string, object> routeData;
                  var route = RouteTable.MatchRoutes(requestUrl, out routeData);
                  if (route == null)
                  {
                      // 404 Not Found
                      throw new HttpException(404, "Not Found!");
                  }
                  // 獲取處理請求的Handler處理程序
                  if (!routeData.ContainsKey("controller"))
                  {
                      // 404 Not Found
                      throw new HttpException(404, "Not Found!");
                  }
                  var handler = route.GetRouteHandler(routeData);
                  // 為當前請求指定Handler處理程序
                  context.RemapHandler(handler);
              }
      
              public void Dispose()
              {
                  this.Dispose();
              }
          }

        該UrlRoutingModule通過注冊ASP.NET請求處理管道的第七個事件,來實現對URL地址進行路由規則的處理,并將最后生成的路由數據交給MvcHandler進行后續處理。這里我省略了ASP.NET MVC源碼中MvcRouteHandler生成MvcHandler的步驟,直接丟給MvcHandler處理。

        核心部分有兩點,一是路由規則的匹配,二是為請求指定handler。

        在路由規則的匹配中,通過設置路由數據鍵值對(Dictionary),并將設置好的路有數據傳遞給MvcHandler。具體的流程如下圖所示,這里就不再展示源碼,請自行下載DEMO查看:

        (2)Mvc

        在此文件夾中,實現了三個核心的部分:

        ① 最核心的處理者 : MvcHandler

          public class MvcHandler : IHttpHandler
          {
              private IDictionary<string, object> routeData;
      
              public MvcHandler(IDictionary<string, object> routeData)
              {
                  this.routeData = routeData;
              }
      
              public void ProcessRequest(HttpContext context)
              {
                  var controllerName = routeData["controller"].ToString();
                  // 借助控制器工廠創建具體控制器實例
                  IController controller = DefaultControllerFactory.CreateController(controllerName);
                  // 確保有找到一個Controller處理請求
                  if (controller == null)
                  {
                      // 404 Not Found!
                      throw new HttpException(404, "Not Found");
                  }
                  // 封裝請求
                  var requestContext = new RequestContext { HttpContext = context, RouteData = routeData };
                  // 開始執行
                  var result = controller.Execute(requestContext);
                  result.Execute(requestContext);
              }
      
              public bool IsReusable
              {
                  get
                  {
                      return false;
                  }
              }
          }

        在MvcHandler類中,主要經歷了以下事件:

        ② 花樣的返回類型 : ActionResult 以及它的子類們

        在以往的ASP.NET MVC開發中,我們在Action方法的編寫中,總會看到它們的返回類型都是以ActionResult為基類的各種Result類型。

          /// <summary>
          /// Action統一的返回類型
          /// </summary>
          public abstract class ActionResult
          {
              public abstract void Execute(RequestContext context);
          }

        因此,這里也實現了ActionResult這個抽象類,并以此為基礎實現了ContentResult、JsonResult以及ViewResult。它們的區別就在于是不同的返回類型,因此有不同的處理。

        這里以ContentResult 和 JsonResult 為例,來看看具體做了什么處理。

        [ContentResult]

          public class ContentResult : ActionResult
          {
              private string content;
              private string contentType;
      
              public ContentResult(string content, string contentType)
              {
                  this.content = content;
                  this.contentType = contentType;
              }
      
              public override void Execute(RequestContext context)
              {
                  context.HttpContext.Response.Write(content);
                  context.HttpContext.Response.ContentType = contentType;
              }
          }

        [JsonResult]

          public class JsonResult : ActionResult
          {
              private object paraObj;
      
              public JsonResult(object paraObj)
              {
                  this.paraObj = paraObj;
              }
      
              public override void Execute(RequestContext context)
              {
                  JavaScriptSerializer jss = new JavaScriptSerializer();
                  var json = jss.Serialize(paraObj);
                  context.HttpContext.Response.Write(json);
                  context.HttpContext.Response.ContentType = "application/json";
              }
          }

        相信有經驗的讀者一眼就看穿了,因此這里也就不再多說了。

        ③ 路由的擴展者 : RouteExtend

        在以往的ASP.NET MVC開發中,我們會在Global全局應用處理文件中為項目注冊路由規則,但卻不知道其實我們常用的MapRoute方法其實是一個擴展方法,它并不位于System.Web.Routing這個類庫之中,而是位于System.Web.Mvc這個類庫之中。

        因此,我們也在Mvc文件夾中實現了一個RouteExtend類,它為RouteTable類的Route集合實現了一個擴展方法:

          /// <summary>
          /// Route 的擴展方法所在類
          /// </summary>
          public static class RouteExtend
          {
              /// <summary>
              /// 指定MvcHandler來處理
              /// </summary>
              public static void MapRoute(this IList<Route> source, string urlTemplate, object defaults)
              {
                  MapRoute(source, urlTemplate, defaults, routeData => new MvcHandler(routeData));
              }
      
              /// <summary>
              /// 通過指定實現了IHttpHandler的處理程序來處理
              /// </summary>
              public static void MapRoute(this IList<Route> source, string urlTemplate, object defaults, Func<IDictionary<string, object>, IHttpHandler> handler)
              {
                  source.Add(new Route(urlTemplate, defaults, handler));
              }
          }

        可以看出,MvcHandler是在這里傳入的(Mvc與Routing是單向依賴)。那么,為什么還要提供一個可傳入自定義Handler的接口呢?因為,不同的路由規則有可能需要不同的實現IHttpHandler的處理程序來處理,也不一定就非得是MvcHandler。

        (3)View

        在ASP.NET MVC中提供了aspx與Razor等模板引擎,這里我偷了懶,直接借助了NVelocity模板引擎來實現。因此,這個文件夾中只有一個VelocityHelper類(我直接從網上搜索的),該類可以幫助我們找到指定的HTML并綁定Model實體。

          /// <summary>
          /// NVelocity模板工具類 VelocityHelper
          /// </summary>
          public class VelocityHelper
          {
              private VelocityEngine velocity = null;
              private IContext context = null;
      
              public object YZControl { get; private set; }
      
              /// <summary>
              /// 構造函數
              /// </summary>
              /// <param name="templatDir">模板文件夾路徑</param>
              public VelocityHelper(string templatDir)
              {
                  Init(templatDir);
              }
      
              /// <summary>
              /// 無參數構造函數
              /// </summary>
              public VelocityHelper() { }
      
              /// <summary>
              /// 初始話NVelocity模塊
              /// </summary>
              public void Init(string templatDir)
              {
                  // 創建VelocityEngine實例對象
                  velocity = new VelocityEngine();
      
                  // 使用設置初始化VelocityEngine
                  ExtendedProperties props = new ExtendedProperties();
                  props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");
                  props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, HttpContext.Current.Server.MapPath(templatDir));
                  //props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, Path.GetDirectoryName(HttpContext.Current.Request.PhysicalPath));
                  props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
                  props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
      
                  // 模板的緩存設置
                  props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, true);              //是否緩存
                  props.AddProperty("file.resource.loader.modificationCheckInterval", (Int64)30);    //緩存時間(秒)
      
                  velocity.Init(props);
      
                  // 為模板變量賦值
                  context = new VelocityContext();
              }
      
              /// <summary>
              /// 給模板變量賦值
              /// </summary>
              /// <param name="key">模板變量</param>
              /// <param name="value">模板變量值</param>
              public void Put(string key, object value)
              {
                  if (context == null)
                  {
                      context = new VelocityContext();
                  }
                  context.Put(key, value);
              }
      
              /// <summary>
              /// 顯示模板
              /// </summary>
              /// <param name="templatFileName">模板文件名</param>
              public void Display(string templatFileName)
              {
                  // 從文件中讀取模板
                  Template template = velocity.GetTemplate(templatFileName);
                  // 合并模板
                  StringWriter writer = new StringWriter();
                  template.Merge(context, writer);
                  // 輸出
                  HttpContext.Current.Response.Clear();
                  HttpContext.Current.Response.Write(writer.ToString());
                  HttpContext.Current.Response.Flush();
                  HttpContext.Current.Response.End();
              }
      
              /// <summary>
              /// 根據模板生成靜態頁面
              /// </summary>
              /// <param name="templatFileName"></param>
              /// <param name="htmlpath"></param>
              public void CreateHtml(string templatFileName, string htmlpath)
              {
                  // 從文件中讀取模板
                  Template template = velocity.GetTemplate(templatFileName);
                  // 合并模板
                  StringWriter writer = new StringWriter();
                  template.Merge(context, writer);
                  using (StreamWriter write2 = new StreamWriter(HttpContext.Current.Server.MapPath(htmlpath), false, Encoding.UTF8, 200))
                  {
                      write2.Write(writer);
                      write2.Flush();
                      write2.Close();
                  }
              }
      
              /// <summary>
              /// 根據模板生成靜態頁面
              /// </summary>
              /// <param name="templatFileName"></param>
              /// <param name="htmlpath"></param>
              //public void CreateJS(string templatFileName, string htmlpath)
              //{
              //    //從文件中讀取模板
              //    Template template = velocity.GetTemplate(templatFileName);
              //    //合并模板
              //    StringWriter writer = new StringWriter();
              //    template.Merge(context, writer);
              //    using (StreamWriter write2 = new StreamWriter(HttpContext.Current.Server.MapPath(htmlpath), false, Encoding.UTF8, 200))
              //    {
              //        write2.Write(YZControl.Strings.Html2Js(YZControl.Strings.ZipHtml(writer.ToString())));
              //        write2.Flush();
              //        write2.Close();
              //    }
              //}
          }
      View Code

      三、我的MVC框架應用實例

      3.1 MVC 應用DEMO介紹

        這是一個ASP.NET 空Web應用項目搭建起來的MVC Web應用項目,它移除了自帶的所有引用項目,僅僅保留了System和System.Web,做到了盡可能地“純凈”。通過引入Mvc.Lib核心類庫,建立Controller、Model和View文件夾以及對應的類和HTML來實現MVC模式。

        (1)引入Mvc.Lib核心類庫之后,需要配置一下Web.config,使UrlRoutingModule能夠正常工作:

        <system.web>
          <compilation debug="true" targetFramework="4.5"/>
          <httpRuntime targetFramework="4.5"/>
          <!-- HttpModule配置(IIS6版本) -->
          <httpModules>
            <add name="UrlRoutingModule" type="Manulife.Web.Mvc.Lib.Routing.UrlRoutingModule"/>
          </httpModules>
        </system.web>
        <system.webServer>
          <!-- 配置不去校驗是否是集成模式 -->
          <validation validateIntegratedModeConfiguration="false"/>
          <!-- HttpModule配置(IIS7及以上版本) -->
          <modules>
            <add name="UrlRoutingModule" type="Manulife.Web.Mvc.Lib.Routing.UrlRoutingModule"/>
          </modules>
        </system.webServer>

        (2)新建Global全局處理配置,在Application_Start事件中為項目添加路由規則:

          public class Global : System.Web.HttpApplication
          {
      
              protected void Application_Start(object sender, EventArgs e)
              {
                  // 注冊路由規則1
                  RouteTable.Routes.MapRoute(
                      urlTemplate: "{controller}/{action}/{id}",
                      defaults: new { controller = "Home", action = "Index" }
                      );
                  // 注冊路由規則2
                  RouteTable.Routes.MapRoute(
                      urlTemplate: "{controller}/{action}",
                      defaults: new { controller = "Home", action = "Index" }
                      );
                  // 注冊路由規則3
                  RouteTable.Routes.MapRoute(
                      urlTemplate: "{controller}",
                      defaults: new { controller = "Home", action = "Index" }
                      );
              }
      
          }

        (3)看看Controller是怎么寫的?是不是很熟悉?

          public class HomeController : ControllerBase
          {
              public ActionResult Index(int id, string controller, string action)
              {
                  return new ContentResult(string.Format("<h1>Controller : {0}, Action : {1}, Id : {2}</h1>", controller, action, id), "text/html");
              }
      
              public ActionResult View()
              {
                  return new ViewResult(new { Id = 1, Name = "Edison Chou", Age = 27, Gender = true });
              }
          }

        (4)看看View中的HTML呢?這里使用NVelocity模板引擎提供的語法,操作Model實體對象。

      <!DOCTYPE html>
      <html>
      <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
          <title>Index - View</title>
          <meta charset="utf-8" />
      </head>
      <body>
          <h1>User Name : $model.Name</h1>
          <h1>User Age : $model.Age</h1>
      </body>
      </html>

      3.2 MVC 應用DEMO演示

        (1)默認路由 : home/index -> ContentResult

        (2)請求JsonResult

        (3)請求ViewResult

      附件下載

        Manulife.Web.Mvc : 點我下載

       

      posted @ 2016-03-09 02:23  EdisonZhou  閱讀(14888)  評論(20)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品国产中文字幕| 国产精品激情av在线播放| 人妻中文字幕精品一页| 人妻无码∧V一区二区| 年日韩激情国产自偷亚洲| 国产无遮挡又黄又爽在线视频| 国产精品不卡一区二区三区| 久久99精品久久久久久| 成人麻豆日韩在无码视频| 亚洲中文久久久精品无码| 国产亚洲亚洲国产一二区| 国产视频一区二区三区四区视频| 国产一级黄色片在线播放| 亚洲区一区二区三区精品| 精品国产AV无码一区二区三区 | 亚洲中文字幕无码中文字 | 国产欧美亚洲精品第1页| 亚洲人成电影网站 久久影视| 日韩国产中文字幕精品| 丰满人妻熟妇乱精品视频| 无码抽搐高潮喷水流白浆| 日本高清视频在线www色| 国产精品成人av电影不卡| 亚洲国产精品18久久久久久| av在线播放国产一区| 免费a级毛片18以上观看精品 | 97精品人妻系列无码人妻| 国产精品国产三级国产专i| 久久精品国产99国产精品澳门| 欧美午夜小视频| 国产在线播放专区av| 国产成人亚洲日韩欧美| 麻豆久久久9性大片| 中文字幕人妻中文AV不卡专区 | 狼人大伊人久久一区二区| 国产美女高潮流白浆视频| 人妻日韩人妻中文字幕| 国产精品精品一区二区三| 日日猛噜噜狠狠扒开双腿小说| 思思99热精品在线| 分宜县|