程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 從源碼淺析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler,reactroutehandler

從源碼淺析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler,reactroutehandler

編輯:關於.NET

從源碼淺析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler,reactroutehandler


熟悉WebForm開發的朋友一定都知道,Page類必須實現一個接口,就是IHttpHandler。HttpHandler是一個HTTP請求的真正處理中心,在HttpHandler容器中,ASP.NET Framework調用HttpHandler的ProcessRequest成員方法來對這個HTTP請求進行真正的處理,真正地對客戶端請求的服務器頁面做出編譯和執行。歸根結底,Asp.Net所有的HTTP請求最後都是由IHttpHandler的實現來處理的,Asp.Net MVC框架當然也不例外。下面就從MvcRouteHandler、MvcHandler和MvcHttpHandler三個常見的Handler類來淺析一下MVC是怎麼和IHttpHandler聯系起來進行HTTP請求處理的。

1、MvcRouteHandler

在MVC中MvcApplication通常在Application_Start事件裡實現RegisterRoutes方法:

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

其中RegisterRoutes方法通常類似如下:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

這個方法非常重要,因為正是從這裡開始,Asp.Net應用程序可以和Asp.Net URL Routing組件完美結合起來實現Url優化(MVC和WebForm都可以,可以參考dudu的這一篇)。

從MVC源碼入手,我們發現RouteCollection的MapRoute擴展方法最終都是通過RouteCollectionExtensions的一個靜態方法實現的:

        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")]
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
        {
            if (routes == null)
            {
                throw new ArgumentNullException("routes");
            }
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            Route route = new Route(url, new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(defaults),
                Constraints = new RouteValueDictionary(constraints),
                DataTokens = new RouteValueDictionary()
            };

            if ((namespaces != null) && (namespaces.Length > 0))
            {
                route.DataTokens["Namespaces"] = namespaces;
            }

            routes.Add(name, route);

            return route;
        }

 

大家注意這一行:   Route route = new Route(url, new MvcRouteHandler()),正是通過MvcRouteHandler(其實從命名就可以猜到),Asp.Net的URL Routing組件就和IHttpHandler有了關聯。到這裡我們猜測,MvcRouteHandler一定和IHttpHandler有關系(甚至它可能就是IHttpHandler的一個具體實現),而且URL Routing組件最後一定映射到一個IHttpHandler處理程序來處理相應的HTTP請求。我們來查看MvcRouteHandler具體源碼實現印證一下自己的看法:

/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. All rights reserved.
 *
 * This software is subject to the Microsoft Public License (Ms-PL). 
 * A copy of the license can be found in the license.htm file included 
 * in this distribution.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/

namespace System.Web.Mvc
{
    using System.Web.Routing;
    using System.Web.SessionState;

    public class MvcRouteHandler : IRouteHandler
    {
        private IControllerFactory _controllerFactory;

        public MvcRouteHandler()
        {
        }

        public MvcRouteHandler(IControllerFactory controllerFactory)
        {
            _controllerFactory = controllerFactory;
        }

        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
            return new MvcHandler(requestContext);
        }

        protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)
        {
            string controllerName = (string)requestContext.RouteData.Values["controller"];
            IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
            return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
        }

        #region IRouteHandler Members

        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
        {
            return GetHttpHandler(requestContext);
        }

        #endregion
    }
}

可惜,MvcRouteHandler沒有繼承實現IHttpHandler接口,而是繼承了IRouteHandler接口,但是我們欣喜發現IRouteHandler接口的唯一方法GetHttpHandler返回了一個IHttpHandler,這實在是太讓人感到意料之中的一陣激動了。

 

2、MvcHandler

繼續上面MvcRouteHandler的源碼,我們發現MvcRouteHandler具體實現GetHttpHandler的時候最後new了一個MvcHandler對象返回:

        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
            return new MvcHandler(requestContext);
        }

 

也就是說MvcHandler是IHttpHandler子類確定無疑了。然後查看MvcHandler源碼,發現MvcHandler繼承實現了IHttpAsyncHandler, IHttpHandler, IRequiresSessionState三個無比熟悉的接口。而這三個接口如果都實現了,在MVC框架下是不是任何http請求就可以通吃了呢?從MSDN我們得知,事實不是這樣的:

注意,即使 MvcHandler 實現 IHttpHandler,也不能將其映射為處理程序(例如.mvc 文件擴展名),因為該類不支持無參數構造函數。 (它唯一的構造函數需要一個 RequestContext 對象)

但是,還好,我們還有MvcHttpHandler。

 

3、MvcHttpHandler

如你所知,MvcHttpHandler可以“彌補”MvcHandler的不足,為什麼這樣說呢?其實2中也提到過了,MvcHandler沒有無參的構造函數,因此即使MvcHandler實現了 IHttpHandler接口,在IIS中也不能將其映射為某類文件擴展名的處理程序,需要結合路由模塊使用。

而MvcHttpHandler就提供了不通過路由模塊的情況下直接處理映射的處理程序。通過查看MvcHttpHandler源碼我們發現,MvcHttpHandler繼承實現了UrlRoutingHandler, IHttpAsyncHandler, IRequiresSessionState接口,而UrlRoutingHandler繼承自IHttpHandler。MvcHttpHandler帶無參的構造函數(也就是說我們可以直接new一個MvcHttpHandler無參數對象?不用擔心上下文?希望這裡的解釋不是令人感到費解),而且繼承自UrlRoutingHandler類實現了IHttpHandler接口,因此可以在ASP.NET程序中讓你更加靈活使用用來解決一些問題。

 

參考:

http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvcroutehandler.aspx

http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvchandler.aspx

http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvchttphandler.aspx

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved