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文件中, ...
随机推荐
- Asp.Net Web API 2第十课——使用OWIN自承载Web API
详情请查看http://aehyok.com/Blog/Detail/71.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...
- FusionCharts简单教程(五)-----FusionCharts中的那些特殊符号
在FusionCharts中有些特殊字符,我们需要进行编码操作才能够使用,否则就无法正常显示. 欧元符号 在FusionCharts里显示"€",你需要用 ...
- Linux tr命令
介绍 tr命令可以对来自标准输入的字符进行替换.压缩和删除.tr只能接收来自标准的输入流,不能接收参数. 语法 tr [OPTION]... SET1 [SET2] 注意:SET2是可选项 OPTIO ...
- 细说.NET中的多线程 (五 使用信号量进行同步)
上一节主要介绍了使用锁进行同步,本节主要介绍使用信号量进行同步 使用EventWaitHandle信号量进行同步 EventWaitHandle主要用于实现信号灯机制.信号灯主要用于通知等待的线程.主 ...
- 解决URL中文乱码问题
在做一个HTTPS连接时, 要客户端合成一段HTTPS地址 如果地址含中文的话程序会crash, 检查发现原来是中文没有转码的原因 在NSString库里面找到了下面两个方法 - (NSString ...
- Java 9终于要包含Jigsaw项目了
当Jigsaw在Java 9中最终发布时,这个项目的历史已经超过八年了. 转载于:http://www.itxuexiwang.com/a/liunxjishu/2016/0228/180.html? ...
- Java程序员的日常 —— 《编程思想》持有对象
集合框架可以说是Java里面必备的知识点了,日常的使用中也会遇到各种情况需要使用到集合.下面就简单介绍下各种集合的使用场景: List List可以看做是数组,实现的方式有两种: ArrayList ...
- Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库1.1. 5种常用的Photoshop滤镜,分别针对照片的曝光.风格色调.黑白照片处理.锐利度.降噪这五大 ...
- Atitit.软件与编程语言中的锁机制原理attilax总结
Atitit.软件与编程语言中的锁机制原理attilax总结 1. 用途 (Db,业务数据加锁,并发操作加锁.1 2. 锁得类型 排它锁 "互斥锁 共享锁 乐观锁与悲观锁1 2.1. 自旋锁 ...
- 设置easyui input默认值
/*设置input 焦点*/ $(function () { //集体调用 $(".formTextBoxes input").each(function () { $(this) ...