在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/p/3510829.html,如需转载请自行联系原作者