请选择 进入手机版 | 继续访问电脑版

[ASP.NET] 详解ASP.NET MVC的整个生命周期

[复制链接]
查看127 | 回复30 | 2021-9-15 05:53:57 | 显示全部楼层 |阅读模式
目次

一、先容

我们做开辟 的,尤其是做微软技术栈的,有一个方向是跳不过去的,那就是MVC开辟 。我信任 大家,做ASP.NET MVC 开辟 有的有很长时间,当然,也有刚进入这个行业的。无论怎样 ,假如 有人问你,你知道ASP.NET MVC的生命周期吗?你知道它的来世此生 吗?你知道它和 ASP.NET WEBFORM 有什么区别吗?估计,这些标题 ,有很多人会答不上来,或者说不清楚 。本日 ,我就把我的明白 写出来,也是对我本身 学习的一次回顾和总结吧。当然,由于本人本领 有限,在写的过程中也大概 会有一些错误,盼望 大家多多包涵,当然,更盼望 大家能不灵赐教,我们共同进步。

在开始之前,我们先来说说,ASP.NET Web Form 和 Asp.net MVC 有什么区别,这里说的区别,当然是本质区别,不是实用 语法谁人 层次的。实在 ,提及 来,ASP.NET WEB FORM 和 ASP.NET MVC 它们两个没有本质区别,使用 的都是ASP.NET WEB FORM 的管道处理模子 ,ASP.NET MVC 也是通过扩展 IHttpModule 和 IHttpHandler 来实现的,都是基于 ASP.NET 的 HttpApplication 的管道处理模子 扩展的,在这个层面来说,它们是一样的。当然,大家不要抬杠,我说的本质区别都是在这个方面,不同意的勿喷。

有人会问,ASP.NET MVC  和 ASP.NET WEBAPI 它们会有什么不同吗?好像 WebAPi 能做的,WebMVC都可以完成,第一眼看上去,好像是如许 ,但是它们有着本质的不同。WebAPI 的处理管道是重新写过的,不是基于 HTTPApplication 管道扩展的。ASP.NET WEB API 雷同 专人做专事,它的管道处理模子 更高效,并且有了 Restfull 的概念。当然,大家怎样 向相识 更细的内容,就必要 看源码了。或再说回来,到了 NET CORE 期间 ,二者又融合管道了。

二、MVC生命周期详述

1、我们既然要说 ASP.NET MVC的生命周期,为了给大家一个团体 印象,俗话说,文不如图,我就贴一张图,按着箭头走,信任 大家也会不能明白 。

详解ASP.NET MVC的整个生命周期

2、上图很简单,大家按着箭头走,也能明白 的差不多。以下是按着我的明白 ,划分了4个模块。

(1)、路由模块

RouteBase 是对路由规则的抽象,也就是说,一个 RouteBase 对象,也就代表了一个条 路由规则。在 ASP.NET MVC 中,有一个唯一的子类实现就是 Route ,它同样也是路由规则的代表。我们有了路由规则,肯定 会把这个规则存放在一个地方,这个地方保存了很多路由规则,这个地方就是 RouteCollection,中文叫“路由集合”,由于 这个集合内里 包含的就是 RouteBase 对象。

RouteCollection 就是路由集合,用于保存路由规则对象,它的定义情势 :

  1. [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
  2.   public class RouteCollection : Collection<RouteBase>
  3.   {
  4.    private class ReadLockDisposable : IDisposable
  5.    {
  6.    private ReaderWriterLockSlim _rwLock;
  7.    public ReadLockDisposable(ReaderWriterLockSlim rwLock)
  8.    {
  9.    this._rwLock = rwLock;
  10.    }
  11.    void IDisposable.Dispose()
  12.    {
  13.    this._rwLock.ExitReadLock();
  14.    }
  15.    }
  16. ......
复制代码

RouteTable 就是路由表,实在 它和 RouteCollection 是一样的。       

  1. public class RouteTable
  2. {
  3. private static RouteCollection _instance = new RouteCollection();
  4. public static RouteCollection Routes
  5. {
  6. get
  7. {
  8. return RouteTable._instance;
  9. }
  10. }
  11. }
复制代码

在ASP.NET MVC处理管线中的第一站就是路由模块。当哀求 到达路由模块后,ASP.NET MVC 框架就会根据 RouteTable 中设置 的路由模板来匹配当前哀求 以获得对应的 Controller 和 Action 信息。具体 的匹配过程就是有UrlRoutingModule(System.Web.Routing.UrlRoutingModule)来实现的。假如 碰到 一个匹配的规则,就会立刻 跳出下面的设置 。也就是说,设置 过程是有次序 的,假如 有一个匹配,后面就算有匹配的也不会实行 的。

  1. namespace System.Web.Routing
  2. {
  3. [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
  4. public class UrlRoutingModule : IHttpModule
  5. {
  6. private static readonly object _contextKey = new object();
  7. private static readonly object _requestDataKey = new object();
  8. private RouteCollection _routeCollection;
  9. public RouteCollection RouteCollection
  10. {
  11. get
  12. {
  13. if (this._routeCollection == null)
  14. {
  15. this._routeCollection = RouteTable.Routes;
  16. }
  17. return this._routeCollection;
  18. }
  19. set
  20. {
  21. this._routeCollection = value;
  22. }
  23. }
  24. protected virtual void Dispose()
  25. {
  26. }
  27. protected virtual void Init(HttpApplication application)
  28. {
  29. if (application.Context.Items[UrlRoutingModule._contextKey] != null)
  30. {
  31. return;
  32. }
  33. application.Context.Items[UrlRoutingModule._contextKey] = UrlRoutingModule._contextKey;
  34. application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
  35. }
  36. private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
  37. {
  38. HttpApplication httpApplication = (HttpApplication)sender;
  39. HttpContextBase context = new HttpContextWrapper(httpApplication.Context);
  40. this.PostResolveRequestCache(context);
  41. }
  42. [Obsolete("This method is obsolete. Override the Init method to use the PostMapRequestHandler event.")]
  43. public virtual void PostMapRequestHandler(HttpContextBase context)
  44. {
  45. }
  46. public virtual void PostResolveRequestCache(HttpContextBase context)
  47. {
  48. RouteData routeData = this.RouteCollection.GetRouteData(context); 第一步匹配路由规则
  49. if (routeData == null)
  50. {
  51. return;
  52. }
  53. IRouteHandler routeHandler = routeData.RouteHandler; 第二步:如有匹配,就找到RouteHandler对象,该类型的实例是:MvcRouteHandler。
  54. if (routeHandler == null)
  55. {
  56. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
  57. }
  58. if (routeHandler is StopRoutingHandler)
  59. {
  60. return;
  61. }
  62. RequestContext requestContext = new RequestContext(context, routeData);
  63. context.Request.RequestContext = requestContext;
  64. IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);第三步,根据 RouteHandler 对象,找到最终处理请求的 IHttpHandler 的对象,该类型是 MvcHandler
  65. if (httpHandler == null)
  66. {
  67. throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[]
  68. {
  69. routeHandler.GetType()
  70. }));
  71. }
  72. if (!(httpHandler is UrlAuthFailureHandler))
  73. {
  74. context.RemapHandler(httpHandler);第四步,有找到的 IHttpHandler 处理请求。
  75. return;
  76. }
  77. if (FormsAuthenticationModule.FormsAuthRequired)
  78. {
  79. UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
  80. return;
  81. }
  82. throw new HttpException(401, SR.GetString("Assess_Denied_Description3"));
  83. }
  84. void IHttpModule.Dispose()
  85. {
  86. this.Dispose();
  87. }
  88. void IHttpModule.Init(HttpApplication application)
  89. {
  90. this.Init(application);
  91. }
  92. }
  93. }
复制代码

(2)、Controller 创建模块

颠末 了路由模块,天生 了 RouteData 路由数据,它包含了根据路由规则匹配的 Controller 和 Action。有了路由数据,必要 有处理器来处理哀求 ,这个任务 就交给了 RouteData 的 RouteHandler 属性,它的范例 是 IRouteHandler,它的值就是MvcRouteHandler,MvcRouteHandler 调用 GetHttpHandler 获取处理哀求 的 IHttpHandler 对象,在 MVC 框架中就是 MvcHandler,具体 代码如下:

  1. namespace System.Web.Mvc
  2. {
  3. /// <summary>Selects the controller that will handle an HTTP request.</summary>
  4. public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
  5. {
  6. private struct ProcessRequestState
  7. {
  8. internal IAsyncController AsyncController;
  9. internal IControllerFactory Factory;
  10. internal RequestContext RequestContext;
  11. internal void ReleaseController()
  12. {
  13. this.Factory.ReleaseController(this.AsyncController);
  14. }
  15. }
  16. [CompilerGenerated]
  17. [Serializable]
  18. private sealed class <>c
  19. {
  20. public static readonly MvcHandler.<>c <>9 = new MvcHandler.<>c();
  21. public static BeginInvokeDelegate<MvcHandler.ProcessRequestState> <>9__20_0;
  22. public static EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> <>9__20_1;
  23. public static Func<KeyValuePair<string, object>, bool> <>9__26_0;
  24. internal IAsyncResult <BeginProcessRequest>b__20_0(AsyncCallback asyncCallback, object asyncState, MvcHandler.ProcessRequestState innerState)
  25. {
  26. IAsyncResult result;
  27. try
  28. {
  29. result = innerState.AsyncController.BeginExecute(innerState.RequestContext, asyncCallback, asyncState);
  30. }
  31. catch
  32. {
  33. innerState.ReleaseController();
  34. throw;
  35. }
  36. return result;
  37. }
  38. internal void <BeginProcessRequest>b__20_1(IAsyncResult asyncResult, MvcHandler.ProcessRequestState innerState)
  39. {
  40. try
  41. {
  42. innerState.AsyncController.EndExecute(asyncResult);
  43. }
  44. finally
  45. {
  46. innerState.ReleaseController();
  47. }
  48. }
  49. internal bool <RemoveOptionalRoutingParameters>b__26_0(KeyValuePair<string, object> entry)
  50. {
  51. return entry.Value == UrlParameter.Optional;
  52. }
  53. }
  54. private static readonly object _processRequestTag = new object();
  55. internal static readonly string MvcVersion = MvcHandler.GetMvcVersionString();
  56. /// <summary>Contains the header name of the ASP.NET MVC version.</summary>
  57. public static readonly string MvcVersionHeaderName = "X-AspNetMvc-Version";
  58. private ControllerBuilder _controllerBuilder;
  59. internal ControllerBuilder ControllerBuilder
  60. {
  61. get
  62. {
  63. if (this._controllerBuilder == null)
  64. {
  65. this._controllerBuilder = ControllerBuilder.Current;
  66. }
  67. return this._controllerBuilder;
  68. }
  69. set
  70. {
  71. this._controllerBuilder = value;
  72. }
  73. }
  74. /// <summary>Gets or sets a value that indicates whether the MVC response header is disabled.</summary>
  75. /// <returns>true if the MVC response header is disabled; otherwise, false.</returns>
  76. public static bool DisableMvcResponseHeader
  77. {
  78. get;
  79. set;
  80. }
  81. /// <summary>Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance.</summary>
  82. /// <returns>true if the <see cref="T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.</returns>
  83. protected virtual bool IsReusable
  84. {
  85. get
  86. {
  87. return false;
  88. }
  89. }
  90. /// <summary>Gets the request context.</summary>
  91. /// <returns>The request context.</returns>
  92. public RequestContext RequestContext
  93. {
  94. get;
  95. private set;
  96. }
  97. /// <summary>Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance.</summary>
  98. /// <returns>true if the <see cref="T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.</returns>
  99. bool IHttpHandler.IsReusable
  100. {
  101. get
  102. {
  103. return this.IsReusable;
  104. }
  105. }
  106. /// <summary>Initializes a new instance of the <see cref="T:System.Web.Mvc.MvcHandler" /> class.</summary>
  107. /// <param name="requestContext">The request context.</param>
  108. /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext" /> parameter is null.</exception>
  109. public MvcHandler(RequestContext requestContext)
  110. {
  111. if (requestContext == null)
  112. {
  113. throw new ArgumentNullException("requestContext");
  114. }
  115. this.RequestContext = requestContext;
  116. }
  117. /// <summary>Adds the version header by using the specified HTTP context.</summary>
  118. /// <param name="httpContext">The HTTP context.</param>
  119. protected internal virtual void AddVersionHeader(HttpContextBase httpContext)
  120. {
  121. if (!MvcHandler.DisableMvcResponseHeader)
  122. {
  123. httpContext.Response.AppendHeader(MvcHandler.MvcVersionHeaderName, MvcHandler.MvcVersion);
  124. }
  125. }
  126. /// <summary>Called by ASP.NET to begin asynchronous request processing.</summary>
  127. /// <returns>The status of the asynchronous call.</returns>
  128. /// <param name="httpContext">The HTTP context.</param>
  129. /// <param name="callback">The asynchronous callback method.</param>
  130. /// <param name="state">The state of the asynchronous object.</param>
  131. protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
  132. {
  133. HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
  134. return this.BeginProcessRequest(httpContext2, callback, state);
  135. }
  136. /// <summary>Called by ASP.NET to begin asynchronous request processing using the base HTTP context.</summary>
  137. /// <returns>The status of the asynchronous call.</returns>
  138. /// <param name="httpContext">The HTTP context.</param>
  139. /// <param name="callback">The asynchronous callback method.</param>
  140. /// <param name="state">The state of the asynchronous object.</param>
  141. protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
  142. {
  143. IController controller;
  144. IControllerFactory factory;
  145. this.ProcessRequestInit(httpContext, out controller, out factory);
  146. IAsyncController asyncController = controller as IAsyncController;
  147. if (asyncController != null)
  148. {
  149. BeginInvokeDelegate<MvcHandler.ProcessRequestState> arg_51_0;
  150. if ((arg_51_0 = MvcHandler.<>c.<>9__20_0) == null)
  151. {
  152. arg_51_0 = (MvcHandler.<>c.<>9__20_0 = new BeginInvokeDelegate<MvcHandler.ProcessRequestState>(MvcHandler.<>c.<>9.<BeginProcessRequest>b__20_0));
  153. }
  154. BeginInvokeDelegate<MvcHandler.ProcessRequestState> beginDelegate = arg_51_0;
  155. EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> arg_71_0;
  156. if ((arg_71_0 = MvcHandler.<>c.<>9__20_1) == null)
  157. {
  158. arg_71_0 = (MvcHandler.<>c.<>9__20_1 = new EndInvokeVoidDelegate<MvcHandler.ProcessRequestState>(MvcHandler.<>c.<>9.<BeginProcessRequest>b__20_1));
  159. }
  160. EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> endDelegate = arg_71_0;
  161. MvcHandler.ProcessRequestState invokeState = new MvcHandler.ProcessRequestState
  162. {
  163. AsyncController = asyncController,
  164. Factory = factory,
  165. RequestContext = this.RequestContext
  166. };
  167. SynchronizationContext synchronizationContext = SynchronizationContextUtil.GetSynchronizationContext();
  168. return AsyncResultWrapper.Begin<MvcHandler.ProcessRequestState>(callback, state, beginDelegate, endDelegate, invokeState, MvcHandler._processRequestTag, -1, synchronizationContext);
  169. }
  170. Action action = delegate
  171. {
  172. try
  173. {
  174. controller.Execute(this.RequestContext);
  175. }
  176. finally
  177. {
  178. factory.ReleaseController(controller);
  179. }
  180. };
  181. return AsyncResultWrapper.BeginSynchronous(callback, state, action, MvcHandler._processRequestTag);
  182. }
  183. /// <summary>Called by ASP.NET when asynchronous request processing has ended.</summary>
  184. /// <param name="asyncResult">The asynchronous result.</param>
  185. protected internal virtual void EndProcessRequest(IAsyncResult asyncResult)
  186. {
  187. AsyncResultWrapper.End(asyncResult, MvcHandler._processRequestTag);
  188. }
  189. private static string GetMvcVersionString()
  190. {
  191. return new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString(2);
  192. }
  193. /// <summary>Processes the request by using the specified HTTP request context.</summary>
  194. /// <param name="httpContext">The HTTP context.</param>
  195. protected virtual void ProcessRequest(HttpContext httpContext)
  196. {
  197. HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
  198. this.ProcessRequest(httpContext2);
  199. }
  200. /// <summary>Processes the request by using the specified base HTTP request context.</summary>
  201. /// <param name="httpContext">The HTTP context.</param>
  202. protected internal virtual void ProcessRequest(HttpContextBase httpContext)
  203. {
  204. IController controller;
  205. IControllerFactory controllerFactory;
  206. this.ProcessRequestInit(httpContext, out controller, out controllerFactory);
  207. try
  208. {
  209. controller.Execute(this.RequestContext);
  210. }
  211. finally
  212. {
  213. controllerFactory.ReleaseController(controller);
  214. }
  215. }
  216. private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
  217. {
  218. HttpContext current = HttpContext.Current;
  219. if (current != null)
  220. {
  221. bool? flag = ValidationUtility.IsValidationEnabled(current);
  222. bool flag2 = true;
  223. if (flag.GetValueOrDefault() == flag2 & flag.HasValue)
  224. {
  225. ValidationUtility.EnableDynamicValidation(current);
  226. }
  227. }
  228. this.AddVersionHeader(httpContext);
  229. this.RemoveOptionalRoutingParameters();
  230. string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
  231. factory = this.ControllerBuilder.GetControllerFactory();
  232. controller = factory.CreateController(this.RequestContext, requiredString);
  233. if (controller == null)
  234. {
  235. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
  236. {
  237. factory.GetType(),
  238. requiredString
  239. }));
  240. }
  241. }
  242. private void RemoveOptionalRoutingParameters()
  243. {
  244. IDictionary<string, object> arg_2F_0 = this.RequestContext.RouteData.Values;
  245. Func<KeyValuePair<string, object>, bool> arg_2F_1;
  246. if ((arg_2F_1 = MvcHandler.<>c.<>9__26_0) == null)
  247. {
  248. arg_2F_1 = (MvcHandler.<>c.<>9__26_0 = new Func<KeyValuePair<string, object>, bool>(MvcHandler.<>c.<>9.<RemoveOptionalRoutingParameters>b__26_0));
  249. }
  250. arg_2F_0.RemoveFromDictionary(arg_2F_1);
  251. }
  252. /// <summary>Enables processing of HTTP Web requests by a custom HTTP handler that implements the <see cref="T:System.Web.IHttpHandler" /> interface.</summary>
  253. /// <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>
  254. void IHttpHandler.ProcessRequest(HttpContext httpContext)
  255. {
  256. this.ProcessRequest(httpContext);
  257. }
  258. /// <summary>Called by ASP.NET to begin asynchronous request processing using the base HTTP context.</summary>
  259. /// <returns>The status of the asynchronous call.</returns>
  260. /// <param name="context">The HTTP context.</param>
  261. /// <param name="cb">The asynchronous callback method.</param>
  262. /// <param name="extraData">The data.</param>
  263. IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
  264. {
  265. return this.BeginProcessRequest(context, cb, extraData);
  266. }
  267. /// <summary>Called by ASP.NET when asynchronous request processing has ended.</summary>
  268. /// <param name="result">The asynchronous result.</param>
  269. void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
  270. {
  271. this.EndProcessRequest(result);
  272. }
  273. }
  274. }
  275. HttpRuntime 调用 IHttpHandler 类型的调用 ProcessRequest() 方法,用于处理请求。
  276. protected internal virtual void ProcessRequest(HttpContextBase httpContext)
  277. {
  278. IController controller;
  279. IControllerFactory controllerFactory;
  280. this.ProcessRequestInit(httpContext, out controller, out controllerFactory);创建 IControllerFactory,并创建 IController 对象。
  281. try
  282. {
  283. controller.Execute(this.RequestContext);执行Controller,背后就是调用相应的 Action 方法。
  284. }
  285. finally
  286. {
  287. controllerFactory.ReleaseController(controller);
  288. }
  289. }
复制代码

核心处理哀求 的方法是ProcessRequestInit(),用于创建 IController 和 IControllerFactory 实例。IControllerFactory 的现实 范例 是:DefaultControllerFactory,该范例 用于创建 IController  范例 的实例。

  1. private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
  2. {
  3. HttpContext current = HttpContext.Current;
  4. if (current != null)
  5. {
  6. bool? flag = ValidationUtility.IsValidationEnabled(current);
  7. bool flag2 = true;
  8. if (flag.GetValueOrDefault() == flag2 & flag.HasValue)
  9. {
  10. ValidationUtility.EnableDynamicValidation(current);
  11. }
  12. }
  13. this.AddVersionHeader(httpContext);
  14. this.RemoveOptionalRoutingParameters();
  15. string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
  16. factory = this.ControllerBuilder.GetControllerFactory();
  17. controller = factory.CreateController(this.RequestContext, requiredString);
  18. if (controller == null)
  19. {
  20. throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
  21. {
  22. factory.GetType(),
  23. requiredString
  24. }));
  25. }
  26. }
复制代码

以上加红的代码就是创建 IController 的实例的逻辑。IController 实例创建完成后,判断 是否实现了 IAsyncController 接口,假如 是,就异步实行 Controller 方法的调用,否则就同步实行 。

  1. protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
  2. {
  3. IController controller;
  4. IControllerFactory factory;
  5. this.ProcessRequestInit(httpContext, out controller, out factory);
  6. IAsyncController asyncController = controller as IAsyncController; 判读是否是需要异步执行
  7. if (asyncController != null)异步执行
  8. {
  9. BeginInvokeDelegate<MvcHandler.ProcessRequestState> arg_51_0;
  10. if ((arg_51_0 = MvcHandler.<>c.<>9__20_0) == null)
  11. {
  12. arg_51_0 = (MvcHandler.<>c.<>9__20_0 = new BeginInvokeDelegate<MvcHandler.ProcessRequestState>(MvcHandler.<>c.<>9.<BeginProcessRequest>b__20_0));
  13. }
  14. BeginInvokeDelegate<MvcHandler.ProcessRequestState> beginDelegate = arg_51_0;
  15. EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> arg_71_0;
  16. if ((arg_71_0 = MvcHandler.<>c.<>9__20_1) == null)
  17. {
  18. arg_71_0 = (MvcHandler.<>c.<>9__20_1 = new EndInvokeVoidDelegate<MvcHandler.ProcessRequestState>(MvcHandler.<>c.<>9.<BeginProcessRequest>b__20_1));
  19. }
  20. EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> endDelegate = arg_71_0;
  21. MvcHandler.ProcessRequestState invokeState = new MvcHandler.ProcessRequestState
  22. {
  23. AsyncController = asyncController,
  24. Factory = factory,
  25. RequestContext = this.RequestContext
  26. };
  27. SynchronizationContext synchronizationContext = SynchronizationContextUtil.GetSynchronizationContext();
  28. return AsyncResultWrapper.Begin<MvcHandler.ProcessRequestState>(callback, state, beginDelegate, endDelegate, invokeState, MvcHandler._processRequestTag, -1, synchronizationContext);
  29. }
  30. Action action = delegate//同步执行。
  31. {
  32. try
  33. {
  34. controller.Execute(this.RequestContext);
  35. }
  36. finally
  37. {
  38. factory.ReleaseController(controller);
  39. }
  40. };
  41. return AsyncResultWrapper.BeginSynchronous(callback, state, action, MvcHandler._processRequestTag);
  42. }
复制代码

(3)、Action 实行 模块,通过 ControllerActionInvoker 调用 InvokeAction() 实行 其方法。Action 方法的实行 也有2个版本,一个是异步版本,一个是同步版本。由于 ActionInvoker 实现了 IAsyncActionInvoker 接口,以是 也是以已方式实行 。该范例 是 AsyncControllerActionInvoker。

A、当Controller对象被创建之后,紧接着就会实行 Controler 对象的 Execute(),实在 背后就是调用 InvokeAction() 方法:

  1. public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
  2. {
  3. if (controllerContext == null)
  4. {
  5. throw new ArgumentNullException("controllerContext");
  6. }
  7. if (string.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch())
  8. {
  9. throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
  10. }
  11. ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext);
  12. ActionDescriptor actionDescriptor = this.FindAction(controllerContext, controllerDescriptor, actionName);
  13. if (actionDescriptor != null)
  14. {
  15. FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor); 获取所有过滤器,全局的、控制器的和方法的
  16. try
  17. {
  18. AuthenticationContext authenticationContext = this.InvokeAuthenticationFilters(controllerContext, filters.AuthenticationFilters, actionDescriptor);认证过滤器的执行。
  19. if (authenticationContext.Result != null)
  20. {
  21. AuthenticationChallengeContext authenticationChallengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authenticationContext.Result);
  22. this.InvokeActionResult(controllerContext, authenticationChallengeContext.Result ?? authenticationContext.Result);
  23. }
  24. else
  25. {
  26. AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);授权过滤器的执行。
  27. if (authorizationContext.Result != null)
  28. {
  29. AuthenticationChallengeContext authenticationChallengeContext2 = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authorizationContext.Result);
  30. this.InvokeActionResult(controllerContext, authenticationChallengeContext2.Result ?? authorizationContext.Result);
  31. }
  32. else
  33. {
  34. if (controllerContext.Controller.ValidateRequest)
  35. {
  36. ControllerActionInvoker.ValidateRequest(controllerContext);
  37. }
  38. IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, actionDescriptor); 获取方法执行参数。
  39. ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues); 执行action,同时执行执行方法前后的 IAcctionFilter
  40. AuthenticationChallengeContext authenticationChallengeContext3 = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, actionExecutedContext.Result);
  41. this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, authenticationChallengeContext3.Result ?? actionExecutedContext.Result); 执行 ActionResult,同时执行方法前后的 IResultFilter
  42. }
  43. }
  44. }
  45. catch (ThreadAbortException)
  46. {
  47. throw;
  48. }
  49. catch (Exception exception)
  50. {
  51. ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, exception);
  52. if (!exceptionContext.ExceptionHandled)
  53. {
  54. throw;
  55. }
  56. this.InvokeActionResult(controllerContext, exceptionContext.Result);//异常过滤器的执行。
  57. }
  58. return true;
  59. }
  60. return false;
  61. }
复制代码

B、当选择完合适的Action后,接着就是 ModelBinder(默认是System.Web.Mvc.DefaultModelBinder),它会从http哀求 的参数中提取数据并实现范例 转换,数据校验(比方 是否必填,数据格式等)以及是否主动 装配到action方法的参数中System.Web.Mvc.DefaultModelBinder

  1. protected virtual IDictionary<string, object> GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
  2. {
  3. Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
  4. ParameterDescriptor[] parameters = actionDescriptor.GetParameters();
  5. for (int i = 0; i < parameters.Length; i++)
  6. {
  7. ParameterDescriptor parameterDescriptor = parameters[i];
  8. dictionary[parameterDescriptor.ParameterName] = this.GetParameterValue(controllerContext, parameterDescriptor);
  9. }
  10. return dictionary;
  11. }
  12. protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
  13. {
  14. Type parameterType = parameterDescriptor.ParameterType;
  15. IModelBinder arg_92_0 = this.GetModelBinder(parameterDescriptor);
  16. IValueProvider valueProvider = controllerContext.Controller.ValueProvider;
  17. string modelName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
  18. Predicate<string> propertyFilter = ControllerActionInvoker.GetPropertyFilter(parameterDescriptor);
  19. ModelBindingContext bindingContext = new ModelBindingContext
  20. {
  21. FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null,
  22. ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType),
  23. ModelName = modelName,
  24. ModelState = controllerContext.Controller.ViewData.ModelState,
  25. PropertyFilter = propertyFilter,
  26. ValueProvider = valueProvider
  27. };
  28. return arg_92_0.BindModel(controllerContext, bindingContext) ?? parameterDescriptor.DefaultValue;
  29. }
复制代码

C、Authentication Filter是mvc5中新增的一个Filter,它会先于authorization filter实行 ,目的 是对访问用户的认证。在MVC5之前,认证和授权都是通过authorization filter来实现的,但如今 这2个操作就分开来了,各自管各自喽。

  1. AuthenticationContext authenticationContext = this.InvokeAuthenticationFilters(controllerContext, filters.AuthenticationFilters, actionDescriptor);
  2. if (authenticationContext.Result != null)
  3. {
  4. AuthenticationChallengeContext authenticationChallengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authenticationContext.Result);
  5. this.InvokeActionResult(controllerContext, authenticationChallengeContext.Result ?? authenticationContext.Result);
  6. }
复制代码

D、Action filters有2个方法OnActionExecuting和OnActionExecuted分别在action实行 前后实行 。我们也可以通过实现IActionFilter接口来实现你个性化的过滤机制

  1. protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
  2. {
  3. ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
  4. Func<ActionExecutedContext> seed = () => new ActionExecutedContext(controllerContext, actionDescriptor, false, null)
  5. {
  6. Result = this.InvokeActionMethod(controllerContext, actionDescriptor, parameters)
  7. };
  8. return filters.Reverse<IActionFilter>().Aggregate(seed, (Func<ActionExecutedContext> next, IActionFilter filter) => () => ControllerActionInvoker.InvokeActionMethodFilter(filter, preContext, next))();
  9. }
复制代码

E、接下来就是实行 我们平常 在Action方法中写的代码了(根据哀求 相应效果 )

  1. protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
  2. {
  3. object actionReturnValue = actionDescriptor.Execute(controllerContext, parameters);
  4. return this.CreateActionResult(controllerContext, actionDescriptor, actionReturnValue);
  5. }
复制代码

(4)、ActionResult 实行 模块。

A、在 ActionResult 实行 前后,仍旧 会有一个filter(IResultFilter),同样的,通过实现 IResultFilter 接口你可以定制本身 的过滤逻辑。

  1. namespace System.Web.Mvc
  2. {
  3. /// <summary>Defines the methods that are required for a result filter.</summary>
  4. public interface IResultFilter
  5. {
  6. /// <summary>Called before an action result executes.</summary>
  7. /// <param name="filterContext">The filter context.</param>
  8. void OnResultExecuting(ResultExecutingContext filterContext);
  9. /// <summary>Called after an action result executes.</summary>
  10. /// <param name="filterContext">The filter context.</param>
  11. void OnResultExecuted(ResultExecutedContext filterContext);
  12. }
  13. }
复制代码

 B、ActionResult 就是把处理的用户哀求 效果 返回。因此 ViewResult, PartialViewResult, RedirectToRouteResult, RedirectResult, ContentResult, JsonResult, FileResult and EmptyResult就是具体 的返回范例 。

C、上面的返回范例 可以大致分为2类:ViewResult 和非ViewResult。对于必要 天生 html页面给客户端的划到ViewResult,而其他的比方 返回文本,json数据等则划分到非ViewResult,对于非ViewResult直接返回就可以了。

View的初始化和渲染呈现

A、对于 ViewResult 终极 是由合适的 View Engine 通过调用 IView 的 Render() 方法来渲染的:

  1. namespace System.Web.Mvc
  2. {
  3. /// <summary>Defines the methods that are required for a view engine.</summary>
  4. public interface IViewEngine
  5. {
  6. /// <summary>Finds the specified partial view by using the specified controller context.</summary>
  7. /// <returns>The partial view.</returns>
  8. /// <param name="controllerContext">The controller context.</param>
  9. /// <param name="partialViewName">The name of the partial view.</param>
  10. /// <param name="useCache">true to specify that the view engine returns the cached view, if a cached view exists; otherwise, false.</param>
  11. ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
  12. /// <summary>Finds the specified view by using the specified controller context.</summary>
  13. /// <returns>The page view.</returns>
  14. /// <param name="controllerContext">The controller context.</param>
  15. /// <param name="viewName">The name of the view.</param>
  16. /// <param name="masterName">The name of the master.</param>
  17. /// <param name="useCache">true to specify that the view engine returns the cached view, if a cached view exists; otherwise, false.</param>
  18. ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
  19. /// <summary>Releases the specified view by using the specified controller context.</summary>
  20. /// <param name="controllerContext">The controller context.</param>
  21. /// <param name="view">The view.</param>
  22. void ReleaseView(ControllerContext controllerContext, IView view);
  23. }
  24. }
复制代码
  1. namespace System.Web.Mvc
  2. {
  3. /// <summary>Defines the methods that are required for a view.</summary>
  4. public interface IView
  5. {
  6. /// <summary>Renders the specified view context by using the specified the writer object.</summary>
  7. /// <param name="viewContext">The view context.</param>
  8. /// <param name="writer">The writer object.</param>
  9. void Render(ViewContext viewContext, TextWriter writer);
  10. }
  11. }
复制代码

 B、整个处理过程是由 IViewEngine 来实现的。ASP.NET MVC 默认提供 WebForm(.aspx)和 Razor(.cshtml) 模板引擎,你可以通过实现 IViewEngine 接口来实现本身 的 ViewEngine,然后在Application_Start方法中做如下注册:

  1. protected void Application_Start()
  2. {
  3. //移除所有的View引擎包括Webform和Razor
  4. ViewEngines.Engines.Clear();
  5. //注册你自己的View引擎
  6. ViewEngines.Engines.Add(new CustomViewEngine());
  7. }
复制代码

C、末了 ,Html Helpers将帮我们天生 input 标签,基于AJAX的 form 等等。

(5)、作为总结,将每个节点告急 的代码类贴出来。

这就是整个流程的代码节点,有些是同步实行 ,有些是异步实行 ,把握关键点,我这里只是谢了一个大概。

  1. UrlRoutingModule-----RouteCollection.GetRouteData(context)----->IRouteHandler routeHandler = routeData.RouteHandler------》IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext)-----》context.RemapHandler(httpHandler)------->MvcHandler------->ProcessRequest()------>ProcessRequestInit()--------》IController------>controller.Execute(this.RequestContext)-------->ControllerActionInvoker------->InvoleAction()--------->InvoleActionMethod()------->InvoleActionReslt()
复制代码

三、竣事

本日 就到这里了,东西固然 不多,但是也写了2个多小时。本日 就算本身 有学习了一边,大家肯定 要好好的把握这个流程,对于办理 程序中的标题 ,扩展框架都有很大的好处。我们作为程序员的,应该要知道其一,也要知道其二。没事,看看源码,我们对框架和我们本身 的代码有更深的相识 。当然,如许 做也是有代价的,必要 更多的时间去支持,我信任 我们的付出是值得。不忘初心,继续积极 。老天不会辜负积极 的人。

到此这篇关于详解ASP.NET MVC的整个生命周期的文章就先容 到这了,更多干系 ASP.NET MVC 生命周期内容请搜索 脚本之家从前 的文章或继续欣赏 下面的干系 文章盼望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 今夕何夕535 | 2021-9-22 20:13:50 | 显示全部楼层
今天是个特别的日子,值得纪念!
回复

使用道具 举报

avatar 蓝色的天空888 | 2021-9-26 16:27:45 | 显示全部楼层
admin楼主的文笔不错!
回复

使用道具 举报

avatar 北右酝 | 2021-10-1 22:17:52 | 显示全部楼层
我就搞不明白了,看帖回帖能死人么,居然只有我这么认真的在回帖!
回复

使用道具 举报

avatar 李悔之2015 | 2021-10-4 09:04:35 | 显示全部楼层
有机会找admin楼主好好聊聊!
回复

使用道具 举报

avatar 123457524 | 2021-10-4 14:05:10 | 显示全部楼层
态度决定一切,不错!
回复

使用道具 举报

avatar xwuw13 | 2021-10-4 14:53:55 | 显示全部楼层
谢谢admin楼主的分享!
回复

使用道具 举报

avatar 晴空万里659 | 2021-10-4 14:54:58 | 显示全部楼层
admin楼主,您提前出院了?
回复

使用道具 举报

avatar 华梦一生 | 2021-10-5 02:32:51 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,他卖的服务器是永久的,我们的网站用 服务器都是在这家买的,你可以去试试。访问地址:http://fwq.mxswl.com
回复

使用道具 举报

avatar 烟织成愁撼 | 2021-10-5 03:56:57 | 显示全部楼层
看了这么多帖子,第一次看到这么高质量内容!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则