MVC的控制器的激活过程,我们从MvcHandler开始讲,前面的事情以后再讲
一、从MvcHandler开始(不要觉得是代码,让你看懂才是最重要的)
using Microsoft.Web.Infrastructure.DynamicValidationHelper;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Web.Mvc.Async;
using System.Web.Mvc.Properties;
using System.Web.Routing;
using System.Web.SessionState;
namespace System.Web.Mvc
{
/// <summary>Selects the controller that will handle an HTTP request.</summary>
public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
private static readonly object _processRequestTag = new object();
internal static readonly string MvcVersion = MvcHandler.GetMvcVersionString();
/// <summary>Contains the header name of the ASP.NET MVC version.</summary>
public static readonly string MvcVersionHeaderName = "X-AspNetMvc-Version";
private ControllerBuilder _controllerBuilder;
internal ControllerBuilder ControllerBuilder
{
get
{
if (this._controllerBuilder == null)
{
this._controllerBuilder = ControllerBuilder.Current;
}
return this._controllerBuilder;
}
set
{
this._controllerBuilder = value;
}
}
/// <summary>Gets or sets a value that indicates whether the MVC response header is disabled.</summary>
/// <returns>true if the MVC response header is disabled; otherwise, false.</returns>
public static bool DisableMvcResponseHeader
{
get;
set;
}
/// <summary>Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance.</summary>
/// <returns>true if the <see cref="T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.</returns>
protected virtual bool IsReusable
{
get
{
return false;
}
}
/// <summary>Gets the request context.</summary>
/// <returns>The request context.</returns>
public RequestContext RequestContext
{
get;
private set;
}
/// <summary>Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance.</summary>
/// <returns>true if the <see cref="T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.</returns>
bool IHttpHandler.IsReusable
{
get
{
return this.IsReusable;
}
}
/// <summary>Initializes a new instance of the <see cref="T:System.Web.Mvc.MvcHandler" /> class.</summary>
/// <param name="requestContext">The request context.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext" /> parameter is null.</exception>
public MvcHandler(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
this.RequestContext = requestContext;
}
/// <summary>Adds the version header by using the specified HTTP context.</summary>
/// <param name="httpContext">The HTTP context.</param>
protected internal virtual void AddVersionHeader(HttpContextBase httpContext)
{
if (!MvcHandler.DisableMvcResponseHeader)
{
httpContext.Response.AppendHeader(MvcHandler.MvcVersionHeaderName, MvcHandler.MvcVersion);
}
}
/// <summary>Called by ASP.NET to begin asynchronous request processing.</summary>
/// <returns>The status of the asynchronous call.</returns>
/// <param name="httpContext">The HTTP context.</param>
/// <param name="callback">The asynchronous callback method.</param>
/// <param name="state">The state of the asynchronous object.</param>
protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
return this.BeginProcessRequest(httpContext2, callback, state);
}
/// <summary>Called by ASP.NET to begin asynchronous request processing using the base HTTP context.</summary>
/// <returns>The status of the asynchronous call.</returns>
/// <param name="httpContext">The HTTP context.</param>
/// <param name="callback">The asynchronous callback method.</param>
/// <param name="state">The state of the asynchronous object.</param>
protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
IController controller;
IControllerFactory factory;
this.ProcessRequestInit(httpContext, out controller, out factory);
IAsyncController asyncController = controller as IAsyncController;
if (asyncController != null)
{
BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
{
IAsyncResult result;
try
{
result = asyncController.BeginExecute(this.RequestContext, asyncCallback, asyncState);
}
catch
{
factory.ReleaseController(asyncController);
throw;
}
return result;
};
EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult)
{
try
{
asyncController.EndExecute(asyncResult);
}
finally
{
factory.ReleaseController(asyncController);
}
};
SynchronizationContext synchronizationContext = SynchronizationContextUtil.GetSynchronizationContext();
AsyncCallback callback2 = AsyncUtil.WrapCallbackForSynchronizedExecution(callback, synchronizationContext);
return AsyncResultWrapper.Begin(callback2, state, beginDelegate, endDelegate, MvcHandler._processRequestTag);
}
Action action = delegate
{
try
{
controller.Execute(this.RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
};
return AsyncResultWrapper.BeginSynchronous(callback, state, action, MvcHandler._processRequestTag);
}
/// <summary>Called by ASP.NET when asynchronous request processing has ended.</summary>
/// <param name="asyncResult">The asynchronous result.</param>
protected internal virtual void EndProcessRequest(IAsyncResult asyncResult)
{
AsyncResultWrapper.End(asyncResult, MvcHandler._processRequestTag);
}
private static string GetMvcVersionString()
{
return new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString();
}
/// <summary>Processes the request by using the specified HTTP request context.</summary>
/// <param name="httpContext">The HTTP context.</param>
protected virtual void ProcessRequest(HttpContext httpContext)
{
HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
this.ProcessRequest(httpContext2);
}
/// <summary>Processes the request by using the specified base HTTP request context.</summary>
/// <param name="httpContext">The HTTP context.</param>
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory controllerFactory;
this.ProcessRequestInit(httpContext, out controller, out controllerFactory);
try
{
controller.Execute(this.RequestContext);
}
finally
{
controllerFactory.ReleaseController(controller);
}
}
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
HttpContext current = HttpContext.Current;
if (current != null && ValidationUtility.IsValidationEnabled(current) == true)
{
ValidationUtility.EnableDynamicValidation(current);
}
this.AddVersionHeader(httpContext);
this.RemoveOptionalRoutingParameters();
string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
factory = this.ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(this.RequestContext, requiredString);
if (controller == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
{
factory.GetType(),
requiredString
}));
}
}
private void RemoveOptionalRoutingParameters()
{
RouteValueDictionary values = this.RequestContext.RouteData.Values;
string[] array = (
from entry in values
where entry.Value == UrlParameter.Optional
select entry.Key).ToArray<string>();
string[] array2 = array;
for (int i = ; i < array2.Length; i++)
{
string key = array2[i];
values.Remove(key);
}
}
/// <summary>Enables processing of HTTP Web requests by a custom HTTP handler that implements the <see cref="T:System.Web.IHttpHandler" /> interface.</summary>
/// <param name="httpContext">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) that are used to service HTTP requests.</param>
void IHttpHandler.ProcessRequest(HttpContext httpContext)
{
this.ProcessRequest(httpContext);
}
/// <summary>Called by ASP.NET to begin asynchronous request processing using the base HTTP context.</summary>
/// <returns>The status of the asynchronous call.</returns>
/// <param name="context">The HTTP context.</param>
/// <param name="cb">The asynchronous callback method.</param>
/// <param name="extraData">The data.</param>
IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return this.BeginProcessRequest(context, cb, extraData);
}
/// <summary>Called by ASP.NET when asynchronous request processing has ended.</summary>
/// <param name="result">The asynchronous result.</param>
void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
{
this.EndProcessRequest(result);
}
}
}
我们暂时以MvcHandler为起点,至于前面谁调用了它,大家先自行研究。
系统控制权移交到MvcHandler时,这时候MVC应该说正式上场了,前面我们叫做准备工作吧。
MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
IHttpAsyncHandler, IHttpHandler定义 ASP.NET 为使用自定义 HTTP 处理程序,同时开启了session.
void IHttpHandler.ProcessRequest(HttpContext httpContext)
{
this.ProcessRequest(httpContext);
}
protected virtual void ProcessRequest(HttpContext httpContext)
{
HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
this.ProcessRequest(httpContext2);
}
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory controllerFactory;
this.ProcessRequestInit(httpContext, out controller, out controllerFactory);//初始化工作
try
{
controller.Execute(this.RequestContext);//进入主战场了
}
finally
{
controllerFactory.ReleaseController(controller);
}
}
二、初始化
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
HttpContext current = HttpContext.Current;
if (current != null && ValidationUtility.IsValidationEnabled(current) == true)
{
ValidationUtility.EnableDynamicValidation(current);
}
this.AddVersionHeader(httpContext);//httpContext 封装有关个别 HTTP 请求的所有 HTTP 特定的信息
this.RemoveOptionalRoutingParameters();
string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
factory = this.ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(this.RequestContext, requiredString);//创建了一个controller 对象。
if (controller == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
{
factory.GetType(),
requiredString
}));
}
}
三、主战场
controller.Execute(this.RequestContext);//进入主战场了,controller是IController,但其实一个Controller实例,
而 Controller : ControllerBase,所以进入ControllerBase里面看看
protected virtual void Execute(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
if (requestContext.HttpContext == null)
{
throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext");
}
this.VerifyExecuteCalledOnce();
this.Initialize(requestContext);
using (ScopeStorage.CreateTransientScope())
{
this.ExecuteCore();//也就是调用了Controller 的ExecuteCore方法
}
}
protected override void ExecuteCore()
{
this.PossiblyLoadTempData();
try
{
string requiredString = this.RouteData.GetRequiredString("action");
if (!this.ActionInvoker.InvokeAction(base.ControllerContext, requiredString))
{
this.HandleUnknownAction(requiredString);
}
}
finally
{
this.PossiblySaveTempData();
}
}
public IActionInvoker ActionInvoker
{
get
{
if (this._actionInvoker == null)
{
this._actionInvoker = this.CreateActionInvoker();
}
return this._actionInvoker;
}
set
{
this._actionInvoker = value;
}
}
protected virtual IActionInvoker CreateActionInvoker()
{
IAsyncActionInvoker arg_23_0;
if ((arg_23_0 = this.Resolver.GetService<IAsyncActionInvoker>()) == null)//
// 没有异步的就看看有没有同步的,没有同步的就直接初始化一个异步的。
//这里牵扯到IOC,但系统默认的如下(DefaultDependencyResolver,把它放到了缓存中提高性能(CacheDependencyResolver )),当然可能用户自己定义。
{
arg_23_0 = (this.Resolver.GetService<IActionInvoker>() ?? new AsyncControllerActionInvoker());
}
return arg_23_0;
} public interface IAsyncActionInvoker : IActionInvoker
{ IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state);
bool EndInvokeAction(IAsyncResult asyncResult);
}
{
private readonly ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
private readonly ConcurrentDictionary<Type, IEnumerable<object>> _cacheMultiple = new ConcurrentDictionary<Type, IEnumerable<object>>();
private readonly IDependencyResolver _resolver;
public CacheDependencyResolver(IDependencyResolver resolver)
{
this._resolver = resolver;
}
public object GetService(Type serviceType)
{
return this._cache.GetOrAdd(serviceType, new Func<Type, object>(this._resolver.GetService));
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this._cacheMultiple.GetOrAdd(serviceType, new Func<Type, IEnumerable<object>>(this._resolver.GetServices));
}
}
{
public object GetService(Type serviceType)
{
if (serviceType.IsInterface || serviceType.IsAbstract)
{
return null;
}
object result;
try
{
result = Activator.CreateInstance(serviceType);
}
catch
{
result = null;
}
return result;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return Enumerable.Empty<object>();
}
}
private sealed class CacheDependencyResolver : IDependencyResolver
{
private readonly ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
private readonly ConcurrentDictionary<Type, IEnumerable<object>> _cacheMultiple = new ConcurrentDictionary<Type, IEnumerable<object>>();
private readonly IDependencyResolver _resolver;
public CacheDependencyResolver(IDependencyResolver resolver)
{
this._resolver = resolver;
}
public object GetService(Type serviceType)
{
return this._cache.GetOrAdd(serviceType, new Func<Type, object>(this._resolver.GetService));
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this._cacheMultiple.GetOrAdd(serviceType, new Func<Type, IEnumerable<object>>(this._resolver.GetServices));
}
IActionInvoker,系统采用IOC创建了一个IActionInvoker对应的实例,我们不知道是什么类型,但无非AsyncControllerActionInvoker : ControllerActionInvoker
这两个(当然前者还是继承了后者)
,此处我们以
ControllerActionInvoker作为讨论对象。其中的方法如下
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (string.IsNullOrEmpty(actionName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = this.FindAction(controllerContext, controllerDescriptor, actionName);
if (actionDescriptor != null)
{
FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor);
try
{
AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);
if (authorizationContext.Result != null)
{
this.InvokeActionResult(controllerContext, authorizationContext.Result);
}
else
{
if (controllerContext.Controller.ValidateRequest)
{
ControllerActionInvoker.ValidateRequest(controllerContext);
}
IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, actionDescriptor);
ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues);
this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result);
}
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, exception);
if (!exceptionContext.ExceptionHandled)
{
throw;
}
this.InvokeActionResult(controllerContext, exceptionContext.Result);
}
return true;
}
return false;
}
ControllerDescriptor
封装描述控制器的信息,如控制器的名称、类型和操作 以及一些元数据等
System.Object
System.Web.Mvc.ControllerDescriptor
System.Web.Mvc.Async.ReflectedAsyncControllerDescriptor
System.Web.Mvc.ReflectedControllerDescriptor
下一章我们接着讲Action的执行过程
MVC的控制器的激活过程,我们从MvcHandler开始讲,前面的事情以后再讲的更多相关文章
- MVC中Action的执行过程
接着上一篇:MVC控制器的激活过程 一.代码现行,该伪代码大致解析了Action的执行的过程 try { Run each IAuthorizationFilter's OnAuthorization ...
- .NET/ASP.NET MVC Controller 控制器(IController控制器的创建过程)
阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...
- 三、ASP.NET MVC Controller 控制器(二:IController控制器的创建过程)
阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...
- 白话学习MVC(五)Controller的激活
一.概述 在此系列开篇的时候介绍了MVC的生命周期 , 对于请求的处理,都是将相应的类的方法注册到HttpApplication事件中,通过事件的依次执行从而完成对请求的处理.对于MVC来说,请求是先 ...
- IController控制器的创建过程
.NET/ASP.NET MVC Controller 控制器(二:IController控制器的创建过程) 阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactor ...
- Spring MVC(三)--控制器接受普通请求参数
Spring MVC中控制器接受参数的类方式有以下几种: 普通参数:只要保证前端参数名称和传入控制器的参数名称一致即可,适合参数较少的情况: pojo类型:如果前端传的是一个pojo对象,只要保证参数 ...
- ASP.NET MVC 5 - 控制器
MVC代表: 模型-视图-控制器 .MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程序包含: · Models: 表示该应用程序的数据并使用验证逻辑来强制实施业务规则的数据 ...
- Asp.net MVC进入请求管道的过程
Asp.net MVC进入请求管道的过程 Asp.Net MVC 跟AspNet 入口解释 Asp.Net MVC请求处理过程 mvc 请求模型 mvc的原理 mvc模型 NewMVCPipleLin ...
- MVC 在控制器中获取某个视图动态的HTML代码
ASP.NET MVC 在控制器中获取某个视图动态的HTML代码 如果我们需要动态的用AJAX从服务器端获取HTML代码,拼接字符串是一种不好的方式,所以我们将HTML代码写在cshtml文件中, ...
随机推荐
- Quartz.net 定时调度时间配置格式说明与实例
格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 1 秒 是 0-59 , - * / 2 分 是 0-59 , - * / 3 小时 ...
- Sql Server对象管理器的使用
VS提供了很多便捷的工具,Sql Server对象管理器可以直接在VS里面访问数据库,不用再打开一个Management Studio.这里记录下Sql Server对象管理器的使用. 1.先在视图里 ...
- Java基础之泛型
泛型: (1)为什么会出现泛型? 因为集合存放的数据类型不固定,故往集合里面存放元素时,存在安全隐患, 如果在定义集合时,可以想定义数组一样指定数据类型,那么就可以解决该类安全问题. JDK1.5后出 ...
- js中setTimeout()的使用bug
今天用setTimeout()时,遇到一个奇怪的现象,通过多方面的查询,最终解决了问题,这是setTimeout()设计的时候存在的一点点bug. 代码的作用主要是在三秒后自动关闭本浏览器窗口: 代码 ...
- Java-小练习简单银行程序
2练习1:创建一个简单的银行程序包 练习目标-Java 语言中面向对象的封装性及构造器的使用. 任务 在这个练习里,创建一个简单版本的(账户类)Account类.将这个源文件放入banking程序 ...
- 知方可补不足~row_number,rank,dense_rank,ntile排名函数的用法
回到目录 这篇文章介绍SQL中4个很有意思的函数,我称它的行标函数,它们是row_number,rank,dense_rank和ntile,下面分别进行介绍. 一 row_number:它为数据表加一 ...
- 《Effective Java》—— 创建与销毁对象
本篇主要总结的是<Effecticve Java>中关于创建和销毁对象的内容. 比如: 何时以及如何创建对象 何时以及如何避免创建对象 如何确保及时销毁 如何管理对象销毁前的清理动作 考虑 ...
- fir.im Weekly - Mobile developer 利器分享
工欲善其事,必先利其器.本期 fir.im Weekly 推荐了很多优秀的 Github 项目.iOS/Android 开发工具利器,比如墨__守独立开发的macOS App -- Repo, 帮助 ...
- DOM_01之树及遍历
1.DOM:ECMAScript+DOM+BOM,Document Object Model,核心DOM+HTML DOM+XML DOM: 2.辨析:①HTML:专门编写网页内容的语言:②XHTML ...
- 第五章 运输层(UDP和TCP三次握手,四次挥手分析)
序言 通过这章,可以知道其实三次握手和四次挥手其实真的好简单,通过这章的学习,我相信你也会同样的认为,以后在也不需要听到别人问三次握手的过程而自己一脸懵逼了,觉得人家好屌,其实也就是他懂你不懂,仅 ...