位元組架構師:你真的熟悉ASP.NET MVC的整個生命週期嗎?
尊重原創版權: https://www.gewuweb.com/hot/12421.html
位元組架構師:你真的熟悉ASP.NET MVC的整個生命週期嗎?
一、介紹
我們做開發的,尤其是做微軟技術棧的,有一個方向是跳不過去的,那就是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的生命週期,為了給大家一個整體印象,俗話說,文不如圖,我就貼一張圖,按著箭頭走,相信大家也會不能理解。 **
** 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
8 public ReadLockDisposable(ReaderWriterLockSlim rwLock)
9 {
10 this._rwLock = rwLock;
11 }
12
13 void IDisposable.Dispose()
14 {
15 this._rwLock.ExitReadLock();
16 }
17 }
18 ......
** RouteTable ** 就是路由表,其實它和 RouteCollection 是一樣的。
1 public class RouteTable
2 {
3 private static RouteCollection _instance = new RouteCollection();
4
5 public static RouteCollection Routes
6 {
7 get
8 {
9 return RouteTable._instance;
10 }
11 }
12 }
在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
8 private static readonly object _requestDataKey = new object();
9
10 private RouteCollection _routeCollection;
11
12 public RouteCollection RouteCollection
13 {
14 get
15 {
16 if (this._routeCollection == null)
17 {
18 this._routeCollection = RouteTable.Routes;
19 }
20 return this._routeCollection;
21 }
22 set
23 {
24 this._routeCollection = value;
25 }
26 }
27
28 protected virtual void Dispose()
29 {
30 }
31
32 protected virtual void Init(HttpApplication application)
33 {
34 if (application.Context.Items[UrlRoutingModule._contextKey] != null)
35 {
36 return;
37 }
38 application.Context.Items[UrlRoutingModule._contextKey] = UrlRoutingModule._contextKey;
39 application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
40 }
41
42 private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
43 {
44 HttpApplication httpApplication = (HttpApplication)sender;
45 HttpContextBase context = new HttpContextWrapper(httpApplication.Context);
46 this.PostResolveRequestCache(context);
47 }
48
49 [Obsolete("This method is obsolete. Override the Init method to use the PostMapRequestHandler event.")]
50 public virtual void PostMapRequestHandler(HttpContextBase context)
51 {
52 }
53
54 public virtual void PostResolveRequestCache(HttpContextBase context)
55 {
56 RouteData routeData = this.RouteCollection.GetRouteData(context); 第一步匹配路由規則
57 if (routeData == null)
58 {
59 return;
60 }
61 IRouteHandler routeHandler = routeData.RouteHandler; 第二步:如有匹配,就找到RouteHandler物件,該型別的例項是:MvcRouteHandler。
62 if (routeHandler == null)
63 {
64 throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
65 }
66 if (routeHandler is StopRoutingHandler)
67 {
68 return;
69 }
70 RequestContext requestContext = new RequestContext(context, routeData);
71 context.Request.RequestContext = requestContext;
72 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);第三步,根據 RouteHandler 物件,找到最終處理請求的 IHttpHandler 的物件,該型別是 MvcHandler
73 if (httpHandler == null)
74 {
75 throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[]
76 {
77 routeHandler.GetType()
78 }));
79 }
80 if (!(httpHandler is UrlAuthFailureHandler))
81 {
82 context.RemapHandler(httpHandler);第四步,有找到的 IHttpHandler 處理請求。
83 return;
84 }
85 if (FormsAuthenticationModule.FormsAuthRequired)
86 {
87 UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
88 return;
89 }
90 throw new HttpException(401, SR.GetString("Assess_Denied_Description3"));
91 }
92
93 void IHttpModule.Dispose()
94 {
95 this.Dispose();
96 }
97
98 void IHttpModule.Init(HttpApplication application)
99 {
100 this.Init(application);
101 }
102 }
103 }
** (2)、Controller 建立模組 **
經過了路由模組,生成了 RouteData 路由資料,它包含了根據路由規則匹配的 Controller 和
Action。有了路由資料,需要有處理器來處理請求,這個任務就交給了 RouteData 的 RouteHandler 屬性,它的型別是
IRouteHandler,它的值就是MvcRouteHandler,MvcRouteHandler 呼叫 GetHttpHandler 獲取處理請求的
IHttpHandler 物件,在 MVC 框架中就是 MvcHandler,詳細程式碼如下:
View Code
HttpRuntime 呼叫 IHttpHandler 型別的呼叫 ProcessRequest() 方法,用於處理請求。
1 protected internal virtual void ProcessRequest(HttpContextBase httpContext)
2 {
3 IController controller;
4 IControllerFactory controllerFactory;
5 this.ProcessRequestInit(httpContext, out controller, out controllerFactory);建立 IControllerFactory,並建立 IController 物件。
6 try
7 {
8 controller.Execute(this.RequestContext);執行Controller,背後就是呼叫相應的 Action 方法。
9 }
10 finally
11 {
12 controllerFactory.ReleaseController(controller);
13 }
14 }
核心處理請求的方法是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 }
1 protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
2 {
3 Type parameterType = parameterDescriptor.ParameterType;
4 IModelBinder arg_92_0 = this.GetModelBinder(parameterDescriptor);
5 IValueProvider valueProvider = controllerContext.Controller.ValueProvider;
6 string modelName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
7 Predicate<string> propertyFilter = ControllerActionInvoker.GetPropertyFilter(parameterDescriptor);
8 ModelBindingContext bindingContext = new ModelBindingContext
9 {
10 FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null,
11 ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType),
12 ModelName = modelName,
13 ModelState = controllerContext.Controller.ViewData.ModelState,
14 PropertyFilter = propertyFilter,
15 ValueProvider = valueProvider
16 };
17 return arg_92_0.BindModel(controllerContext, bindingContext) ?? parameterDescriptor.DefaultValue;
18 }
** 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
10 /// <summary>Called after an action result executes.</summary>
11 /// <param name="filterContext">The filter context.</param>
12 void OnResultExecuted(ResultExecutedContext filterContext);
13 }
14 }
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
13 /// <summary>Finds the specified view by using the specified controller context.</summary>
14 /// <returns>The page view.</returns>
15 /// <param name="controllerContext">The controller context.</param>
16 /// <param name="viewName">The name of the view.</param>
17 /// <param name="masterName">The name of the master.</param>
18 /// <param name="useCache">true to specify that the view engine returns the cached view, if a cached view exists; otherwise, false.</param>
19 ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
20
21 /// <summary>Releases the specified view by using the specified controller context.</summary>
22 /// <param name="controllerContext">The controller context.</param>
23 /// <param name="view">The view.</param>
24 void ReleaseView(ControllerContext controllerContext, IView view);
25 }
26 }
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方法中做如下注冊: **
protected void Application_Start()
{
//移除所有的View引擎包括Webform和Razor
ViewEngines.Engines.Clear();
//註冊你自己的View引擎
ViewEngines.Engines.Add(new CustomViewEngine());
}
** C、最後,Html Helpers將幫我們生成 input 標籤,基於AJAX的 form 等等。 **
** (5)、作為總結,將每個節點主要的程式碼類貼出來。 **
這就是整個流程的程式碼節點,有些是同步執行,有些是非同步執行,把握關鍵點,我這裡只是謝了一個大概。
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個多小時。今天就算自己有學習了一邊,大家一定要好好的把握這個流程,對於解決程式中的問題,擴充套件框架都有很大的好處。我們作為程式設計師的,應該要知道其一,也要知道其二。沒事,看看原始碼,我們對框架和我們自己的程式碼有更深的瞭解。當然,這樣做也是有代價的,需要更多的時間去支援,我相信我們的付出是值得。不忘初心,繼續努力。老天不會辜負努力的人。