天天看點

PartialViewResult不鳥_ViewStart.cshtml

概述

  在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中。

PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml

則ViewResult和PartialViewResult的輸出結果相同:

PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml

⑵ 如果視圖設定如下,即:将 Layout = "~/Views/Shared/_Layout.cshtml";定義在_ViewStart.cshtml中。

PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml

則ViewResult和PartialViewResult的輸出結果不同:

PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml

   以上的執行個體,我們可見斷定,對于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);
}
      
PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml

   上圖可以看出,在ViewResult和PartialViewResult的FindView方法中,分别通過base.ViewEngineCollection的FindView和FindPartialView來建立ViewEngineResult對象(用于封裝目前請求的視圖對象和視圖引擎對象),我們知道base.ViewEngineCollection其實就是一個視圖引擎集合(預設情況下有:RazorViewEngine、WebFormViewEngine),而視圖引擎集合的FindView和FindPartialView方法,本質上就是周遊執行每個視圖引擎的FindView和FindPartialView方法。

  由于我們使用的是Razor引擎,所有就以RazorViewEngine為例來介紹:

PartialViewResult不鳥_ViewStart.cshtml
PartialViewResult不鳥_ViewStart.cshtml

this.CreatePartialView(...)和this.CreateView(...)方法都實作在派生類中!

PartialViewResult不鳥_ViewStart.cshtml

  上圖中,我們可以看出在建立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);
	}
}
      

  

PartialViewResult不鳥_ViewStart.cshtml

作者:武沛齊

出處:http://www.cnblogs.com/wupeiqi/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。