感覺好久沒有學習了, 汗. 年就這么過完了, 感覺沒有嘗到過年的味道. 現在的年過的有些冷清了.
除了體重證明著我過了一個年, 還有一件值得開心的事情, 終于把女朋友變成未婚妻了. 這是一大進步吧.
閑話不扯了, 繼續之前沒有完成的學習.
前面 結尾處, 提到了這個方法:
protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) { actionResult.ExecuteResult(controllerContext); }
ExecuteResult方法是一個抽象方法. 那么來看一下, 都是有哪些類中來實現了這一方法.
這里的這些類, 應該還是讓人蠻熟悉的吧. 在Action方法中, return View() / Json() / Content() / File() ...
這里的這些返回方式, 只有View()是還要去查找視圖, 解析視圖, 然后返回視圖的, 所以先來看這個了.
一、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)
這個方法也是一個抽象方法. 其實現類為: System.Web.Mvc.PartialViewResult 和 System.Web.Mvc.ViewResult.
這個方法就是去負責查找需要使用到的視圖.
看一下ViewResult類中, 最終調用的方法
//System.Web.Mvc.VirtualPathProviderViewEngine public 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)); }
查找到視圖之后, 創建一個視圖引擎, 然后返回這個視圖引擎.
2. Render(viewContext, output)
這個方法就是去解析視圖, 主要是為了解析其中的Razor, 生成最后的頁面數據.
//System.Web.Mvc.BuildManagerCompiledView public 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); }
這里的RenderView也有兩種實現類, 我們在vs中建mvc項目的時候, 可能有人注意到過, 視圖有兩種模式可以選, 一種是Razor, 另一種就是WebForm. 事實上, 確實是有兩種語法以供使用的.
那這里只看一下Razor的語法了.
//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.VirtualPathProviderViewEngine public virtual void ReleaseView(ControllerContext controllerContext, IView view) { IDisposable disposable = view as IDisposable; if (disposable != null) { disposable.Dispose(); } }
這里是釋放資源了
二、Json
這個也是常用的, 返回時, 會在內部轉換實體為Json格式字符串. 非常方便好用. 為前端直接提供數據.
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)); } }
文章列表