MVC Controller

来源:互联网 发布:含金量最高的网络教育 编辑:程序博客网 时间:2024/04/30 09:18

转载地址:http://www.cnblogs.com/jyan/archive/2012/07/17/2594508.html


先回顾下之前的MVC执行过程:

一个HttpRequest是如何被ASP.NET和ASP.NET MVC框架执行的:经过IIS和ASP.NET处理后,Core Routing会首先根据URL匹配物理路径上的文件,如果不能匹配则由核心路由模块执行路由,路由被匹配后,MvcRouteHandler会将这个请求“带入”MVC框架,执行Controller和Action。

 

Controller是如何被创建以及执行的呢?

我们看一下MVCRouteHander的源码:

复制代码
namespace System.Web.Mvc{    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"];            if (String.IsNullOrWhiteSpace(controllerName))            {                throw new InvalidOperationException(MvcResources.MvcRouteHandler_RouteValuesHasNoController);            }            IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();            return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);        }        #region IRouteHandler Members        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)        {            return GetHttpHandler(requestContext);        }        #endregion    }}
复制代码

MvcRouteHandler的实现仅仅是通过GetHttpHandler方法返回一个MvcHandler实例。

再来看一下MvcHandler的实现:

 

 


核心方法依然是ProcessRequest(异步版BeginProceessRequest)。

复制代码
protected internal virtual void ProcessRequest(HttpContextBase httpContext)        {            IController controller;            IControllerFactory factory;            ProcessRequestInit(httpContext, out controller, out factory);            try            {                controller.Execute(RequestContext);            }            finally            {                factory.ReleaseController(controller);            }        }
复制代码
ProcessRequestInit方法实现了Controller的创建

复制代码
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)        {            // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks            // at Request.Form) to work correctly without triggering full validation.            // Tolerate null HttpContext for testing.            HttpContext currentContext = HttpContext.Current;            if (currentContext != null)            {                bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);                if (isRequestValidationEnabled == true)                {                    ValidationUtility.EnableDynamicValidation(currentContext);                }            }            AddVersionHeader(httpContext);            RemoveOptionalRoutingParameters();            // Get the controller type            string controllerName = RequestContext.RouteData.GetRequiredString("controller");            // Instantiate the controller and call Execute            factory = ControllerBuilder.GetControllerFactory();            controller = factory.CreateController(RequestContext, controllerName);            if (controller == null)            {                throw new InvalidOperationException(                    String.Format(                        CultureInfo.CurrentCulture,                        MvcResources.ControllerBuilder_FactoryReturnedNull,                        factory.GetType(),                        controllerName));            }        }
复制代码

MvcHandler从RouteData中获得controller名字负责创建一个ControllerBuilder的实例,并通过ControllerBuilder的GetControllerFactory返回一个IControllerFactory的实例,这个实例就是DefaultControllerFactory,它的 CreateController方法负责创建需要的Controller实例

 

// Get the controller typestring controllerName = RequestContext.RouteData.GetRequiredString("controller");// Instantiate the controller and call Executefactory = ControllerBuilder.GetControllerFactory();controller = factory.CreateController(RequestContext, controllerName);

 


Controller的执行:

Controller继承自ControllerBase,而Controller又继承自IController,而IController的定义非常简单:

复制代码
namespace System.Web.Mvc{    public interface IController    {        void Execute(RequestContext requestContext);    }}
复制代码

只有一个Execute()接口。从接口定义可以看出,当Controller被“调用”的时候,应该负责完成Execute方法,参数RequestContext封装了HttpContext。

打开Controller源文件并没有发现Execute()方法的实现,那么它应该在ControllerBase中,查看ControllerBase发现,在,Execute在内部调用ExecuteCore,ExecuteCore作为一个抽象方法,延迟到Controller中实现。ControllerBase只提供了诸如TempData、ViewData等,Controller的ExecuteCore方法真正invoke了action机制,是action的入口。下面的代码是ExecuteCore的实现:

 

复制代码
 protected override void ExecuteCore()        {            // If code in this method needs to be updated, please also check the BeginExecuteCore() and            // EndExecuteCore() methods of AsyncController to see if that code also must be updated.            PossiblyLoadTempData();            try            {                string actionName = RouteData.GetRequiredString("action");                if (!ActionInvoker.InvokeAction(ControllerContext, actionName))                {                    HandleUnknownAction(actionName);                }            }            finally            {                PossiblySaveTempData();            }        }
复制代码

 

可以看到RouteData在这里又提供了action参数,可以想象InvokeAction方法依靠这个action的名字调用action,并实现诸多验证机制

 

0 0