在ASP.NET MVC中,對於Action中獲得的ActionResult若是是一個ViewResult對象,那麼在進行View呈現時,則會先執行_ViewStart.cshtml,而後再去執行被請求的視圖頁,可是若是在控制器的Action中獲得的ActionResult是一個PartialViewResult對象,那麼在進行View呈現時,則不會執行_ViewStart.cshtml。html
例如:控制器代碼以下:web
public class HomeController : Controller { public ActionResult Index() { return View("Index"); } public ActionResult PartView() { return PartialView("Index"); } }
⑴ 若是視圖中設置以下,即:將 Layout = "~/Views/Shared/_Layout.cshtml";定義在Index.cshtml中。
ide
則ViewResult和PartialViewResult的輸出結果相同:
ui
⑵ 若是視圖設置以下,即:將 Layout = "~/Views/Shared/_Layout.cshtml";定義在_ViewStart.cshtml中。
this
則ViewResult和PartialViewResult的輸出結果不一樣:
spa
以上的實例,咱們可見判定,對於PartialViewResult對象進行View呈現時,不會執行 「_ViewStart.cshtml」(由於第二種狀況下沒有執行母板頁中的代碼),爲了更加具備說服力,咱們再來看看ASP.NET MVC源代碼,並對比ViewResult和PartialViewResult來檢查咱們的猜測是否正確!!3d
因爲對於ASP.NET MVC來講,進行View呈現的入口是執行ActionResult的ExecuteResult方法,而ViewResult和PartialViewResult都是繼承自ViewResultBase類,在ViewResultBase中定義了ExecuteResult 方法!orm
public abstract class ViewResultBase : ActionResult { //省略其餘代碼... 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 viewEngineResult = null; if (this.View == null) { //執行FindView方法(在派生類中實現),經過視圖引擎來建立視圖對象! viewEngineResult = this.FindView(context); this.View = viewEngineResult.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 (viewEngineResult != null) { viewEngineResult.ViewEngine.ReleaseView(context, this.View); } } //該方法在派生類ViewResult和PartialViewResult中實現 protected abstract ViewEngineResult FindView(ControllerContext context); }
上圖能夠看出,在ViewResult和PartialViewResult的FindView方法中,分別經過base.ViewEngineCollection的FindView和FindPartialView來建立ViewEngineResult對象(用於封裝當前請求的視圖對象和視圖引擎對象),咱們知道base.ViewEngineCollection其實就是一個視圖引擎集合(默認狀況下有:RazorViewEngine、WebFormViewEngine),而視圖引擎集合的FindView和FindPartialView方法,本質上就是遍歷執行每一個視圖引擎的FindView和FindPartialView方法。htm
因爲咱們使用的是Razor引擎,全部就以RazorViewEngine爲例來介紹:對象
this.CreatePartialView(...)和this.CreateView(...)方法都實如今派生類中!
上圖中,咱們能夠看出在建立RazorView對象時,ViewResult和PartialViewResult的區別在於參數:runViewStartPages,正式因爲它,決定了在以後執行進行視圖頁處理時,也就是執行RazorView對象的Render(viewContext, output)方法時,是否執行「_ViewStar.cshtml」。
public abstract class BuildManagerCompiledView : IView { //省略其餘代碼... public void Render(ViewContext viewContext, TextWriter writer) { if (viewContext == null) { throw new ArgumentNullException("viewContext"); } object obj = null; Type compiledType = this.BuildManager.GetCompiledType(this.ViewPath); if (compiledType != null) { obj = this._viewPageActivator.Create(this._controllerContext, compiledType); } if (obj == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, new object[] { this.ViewPath })); } this.RenderView(viewContext, writer, obj); } //實如今派生類中 protected abstract void RenderView(ViewContext viewContext, TextWriter writer, object instance); } public class RazorView : BuildManagerCompiledView { //省略其餘代碼... protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance) { if (writer == null) { throw new ArgumentNullException("writer"); } WebViewPage webViewPage = instance as WebViewPage; if (webViewPage == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, new object[] { base.ViewPath })); } webViewPage.OverridenLayoutPath = this.LayoutPath; webViewPage.VirtualPath = base.ViewPath; webViewPage.ViewContext = viewContext; webViewPage.ViewData = viewContext.ViewData; webViewPage.InitHelpers(); if (this.VirtualPathFactory != null) { webViewPage.VirtualPathFactory = this.VirtualPathFactory; } if (this.DisplayModeProvider != null) { webViewPage.DisplayModeProvider = this.DisplayModeProvider; } WebPageRenderingBase startPage = null; //在這裏這裏這裏這裏.... if (this.RunViewStartPages) { //執行「_ViewStart.cshtml」中內容! startPage = this.StartPageLookup(webViewPage, RazorViewEngine.ViewStartFileName, this.ViewStartFileExtensions); } WebPageBase arg_D3_0 = webViewPage; HttpContextBase httpContext = viewContext.HttpContext; WebPageRenderingBase page = null; object model = null; arg_D3_0.ExecutePageHierarchy(new WebPageContext(httpContext, page, model), writer, startPage); } }