概述
在ASP.NET MVC中,對于Action中得到的ActionResult如果是一個ViewResult對象,那麼在進行View呈現時,則會先執行_ViewStart.cshtml,然後再去執行被請求的視圖頁,但是如果在控制器的Action中得到的ActionResult是一個PartialViewResult對象,那麼在進行View呈現時,則不會執行_ViewStart.cshtml。
舉例驗證
例如:控制器代碼如下:
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Index");
}
public ActionResult PartView()
{
return PartialView("Index");
}
}
⑴ 如果視圖中設定如下,即:将 Layout = "~/Views/Shared/_Layout.cshtml";定義在Index.cshtml中。

則ViewResult和PartialViewResult的輸出結果相同:
⑵ 如果視圖設定如下,即:将 Layout = "~/Views/Shared/_Layout.cshtml";定義在_ViewStart.cshtml中。

則ViewResult和PartialViewResult的輸出結果不同:
以上的執行個體,我們可見斷定,對于PartialViewResult對象進行View呈現時,不會執行 “_ViewStart.cshtml”(因為第二種情況下沒有執行主機闆頁中的代碼),為了更加具有說服力,我們再來看看ASP.NET MVC源代碼,并對比ViewResult和PartialViewResult來檢查我們的猜想是否正确!!
源碼驗證
由于對于ASP.NET MVC來說,進行View呈現的入口是執行ActionResult的ExecuteResult方法,而ViewResult和PartialViewResult都是繼承自ViewResultBase類,在ViewResultBase中定義了ExecuteResult 方法!
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方法。
由于我們使用的是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);
}
}
作者:武沛齊
出處:http://www.cnblogs.com/wupeiqi/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。