MVC source code analysis, mvc source code
I feel like I haven't learned for a long time, and I have never tasted the New Year.
In addition to proving that I have lived for a year, there is another happy thing that I have finally turned my girlfriend into my fiancee. This is a great improvement.
Continue the learning that has not been completed before.
This method is mentioned at the end:
protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult){ actionResult.ExecuteResult(controllerContext);}
The ExecuteResult method is an abstract method. Let's take a look at the classes that implement this method.
These classes should be quite familiar here. In the Action method, return View ()/Json ()/Content ()/File ()...
Here, only View () is used to find the View, parse the View, and then return the View.
I. View
//System.Web.Mvc.ViewResultBase
public override void ExecuteResult(ControllerContext context){ if (context == null) { throw new ArgumentNullException("context"); } if (string.IsNullOrEmpty(this.ViewName)) { this.ViewName = context.RouteData.GetRequiredString("action"); } ViewEngineResult result = null; if (this.View == null) { result = this.FindView(context); this.View = result.View; } TextWriter output = context.HttpContext.Response.Output; ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output); this.View.Render(viewContext, output); if (result != null) { result.ViewEngine.ReleaseView(context, this.View); }}
1. FindView (context)
This method is also an abstract method. Its implementation class is: System. Web. Mvc. PartialViewResult and System. Web. Mvc. ViewResult.
This method is used to find the view to be used.
Let's take a look at the final method called in the ViewResult class.
//System.Web.Mvc.VirtualPathProviderViewEnginepublic virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache){ string[] strArray; string[] strArray2; if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (string.IsNullOrEmpty(viewName)) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName"); } string requiredString = controllerContext.RouteData.GetRequiredString("controller"); string str2 = this.GetPath(controllerContext, this.ViewLocationFormats, this.AreaViewLocationFormats, "ViewLocationFormats", viewName, requiredString, "View", useCache, out strArray); string str3 = this.GetPath(controllerContext, this.MasterLocationFormats, this.AreaMasterLocationFormats, "MasterLocationFormats", masterName, requiredString, "Master", useCache, out strArray2); if (!string.IsNullOrEmpty(str2) && (!string.IsNullOrEmpty(str3) || string.IsNullOrEmpty(masterName))) { return new ViewEngineResult(this.CreateView(controllerContext, str2, str3), this); } return new ViewEngineResult(strArray.Union<string>(strArray2));}
After finding the view, create a view engine and return to the view engine.
2. Render (viewContext, output)
This method is used to parse the view, mainly to parse the Razor and generate the final page data.
//System.Web.Mvc.BuildManagerCompiledViewpublic void Render(ViewContext viewContext, TextWriter writer){ if (viewContext == null) { throw new ArgumentNullException("viewContext"); } object instance = null; Type compiledType = this.BuildManager.GetCompiledType(this.ViewPath); if (compiledType != null) { instance = this.ViewPageActivator.Create(this._controllerContext, compiledType); } if (instance == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, new object[] { this.ViewPath })); } this.RenderView(viewContext, writer, instance);}
Here, the RenderView also has two implementation classes. When we set up the mvc project in vs, someone may have noticed that there are two modes for the view, one is Razor, the other is WebForm. in fact, there are actually two types of syntax for use.
Now let's take a look at the Razor syntax.
//System.Web.Mvc.RazorView
protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance){ if (writer == null) { throw new ArgumentNullException("writer"); } WebViewPage page = instance as WebViewPage; if (page == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, new object[] { base.ViewPath })); } page.OverridenLayoutPath = this.LayoutPath; page.VirtualPath = base.ViewPath; page.ViewContext = viewContext; page.ViewData = viewContext.ViewData; page.InitHelpers(); if (this.VirtualPathFactory != null) { page.VirtualPathFactory = this.VirtualPathFactory; } if (this.DisplayModeProvider != null) { page.DisplayModeProvider = this.DisplayModeProvider; } WebPageRenderingBase startPage = null; if (this.RunViewStartPages) { startPage = this.StartPageLookup(page, RazorViewEngine.ViewStartFileName, this.ViewStartFileExtensions); } HttpContextBase httpContext = viewContext.HttpContext; WebPageRenderingBase base4 = null; object model = null; page.ExecutePageHierarchy(new WebPageContext(httpContext, base4, model), writer, startPage);}
3. ReleaseView (context, this. View)
//System.Web.Mvc.VirtualPathProviderViewEnginepublic virtual void ReleaseView(ControllerContext controllerContext, IView view){ IDisposable disposable = view as IDisposable; if (disposable != null) { disposable.Dispose(); }}
Resources are released.
Ii. Json
Let's look at another Json file. This is also common.
public override void ExecuteResult(ControllerContext context){ if (context == null) { throw new ArgumentNullException("context"); } if ((this.JsonRequestBehavior == JsonRequestBehavior.DenyGet) && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed); } HttpResponseBase response = context.HttpContext.Response; if (!string.IsNullOrEmpty(this.ContentType)) { response.ContentType = this.ContentType; } else { response.ContentType = "application/json"; } if (this.ContentEncoding != null) { response.ContentEncoding = this.ContentEncoding; } if (this.Data != null) { JavaScriptSerializer serializer = new JavaScriptSerializer(); if (this.MaxJsonLength.HasValue) { serializer.MaxJsonLength = this.MaxJsonLength.Value; } if (this.RecursionLimit.HasValue) { serializer.RecursionLimit = this.RecursionLimit.Value; } response.Write(serializer.Serialize(this.Data)); }}
Directory synchronized