_ViewStart.cshtml布局文件在哪里以及如何链接?


199

这是默认MVC 3模板中的About.cshtml:

@{
    ViewBag.Title = "About Us";
}

<h2>About</h2>
<p>
     Put content here.
</p>

我希望可以在中找到对_ViewStart文件的引用About.cshtml,但显然不是。

我查看了global.asaxweb.config,但是无法找到该About.cshtml文件如何与_ViewStart文件中的布局“链接”在一起。

一切都按预期进行,我只想知道引擎盖下发生了什么...

Answers:


237

ScottGu的博客中

从ASP.NET MVC 3 Beta版本开始,您现在可以在项目的\ Views文件夹下添加一个名为_ViewStart.cshtml(对于VB则为_ViewStart.vbhtml)的文件:

_ViewStart文件可用于定义要在每个视图的呈现开始时执行的通用视图代码。例如,我们可以在_ViewStart.cshtml文件中编写代码,以编程方式将每个视图的Layout属性默认设置为SiteLayout.cshtml文件:

因为此代码在每个View的开头执行,所以我们不再需要在任何单个View文件中显式设置Layout(除非我们想覆盖上面的默认值)。

重要提示:因为_ViewStart.cshtml允许我们编写代码,所以我们可以选择使Layout选择逻辑比基本属性集更丰富。例如:根据访问网站的设备类型,我们可以更改所使用的布局模板-并为这些设备提供经过电话或平板电脑优化的布局,并为PC /笔记本电脑提供桌面优化的布局。或者,如果我们要构建供多个客户使用的CMS系统或通用共享应用程序,则在访问网站时,我们可以根据客户(或其角色)选择不同的布局以使用。

这使用户界面具有很大的灵活性。它还使您可以更轻松地一次编写视图逻辑,并避免在多个位置重复。

另请参阅


14
因此,它或多或少是MVC3的“硬编码”功能?我不需要将其更改为另一个“默认”页面,只是对它的设置方式感到好奇。谢谢您对所有内容进行整理:)
Kman 2012年

2
Kman-硬编码,按照惯例(在这里选择另一个“句柄” :))-是的,完全正确。很高兴它清除了雾
吉姆·托兰

您可能不仅需要在“视图”文件夹中。如果添加自定义RazorViewEngine以便将视图组织到其他文件夹中,则还必须将该文件包括在这些备用视图文件夹的根目录中。例如,我将所有Inspinia模板视图移动到一个文件夹中,并在视图引擎中运行它ViewLocationFormats = ViewLocationFormats.Union(new string[] { "~/Inspinia/ExampleViews/{1}/{0}.cshtml" }).ToArray();。结果,我必须将_ViewStart.cshtml文件的副本添加到“〜/ Inspinia / ExampleViews”中,否则它将不会被拾取并且未设置布局。
Triynko

2
如果您的Views文件夹包含子文件夹,是否可以_ViewStart在每个子文件夹中放置一个链接到该子文件夹中的视图的子文件夹?
toddmo

35

在更一般的意义上,MVC框架“了解” _Viewstart.cshtml的能力称为“按惯例编码”。

约定优于配置(也称为约定编码)是一种软件设计范例,旨在减少开发人员需要做出的决策数量,以简化操作,但不一定会失去灵活性。该短语本质上意味着开发人员只需要指定应用程序的非常规方面。例如,如果模型中有一个Sale类,则默认情况下数据库中的对应表称为“ sales”。仅当有人偏离此约定(例如,将表称为“ products_sold”)时,才需要编写有关这些名称的代码。

维基百科

这没有魔术。它刚刚被写入MVC框架的核心代码库,因此是MVC所“了解”的东西。这就是为什么您无法在.config文件或其他位置找到它的原因;它实际上在MVC代码中。但是,您可以覆盖以更改或取消这些约定。


13
如果MVC知道这一点,那么Visual Studio为什么不知道并向我指出呢?如果按惯例进行编码意味着只要您碰巧不违反该约定就可以正常工作,那么这很烂……
Arne Evertsson

不违反约定是重点。AKAIK Ruby on Rails也遵循此范例。
Umar Farooq Khawaja

+1 Raif。捍卫文献不充分的“按惯例编码”毫无意义。关于我的任何向后代码,我都可以这么说。“什么?当它达到33时,您没想到它会崩溃吗?每个人都知道您跳过了33。” 不幸的是,ASP.NET MVC的文档差距很大。唯一的MS文档是自动生成的,没有内部源摘要。
香农2014年

6
约定优于配置并不意味着您不能更改它。应该有配置可以用来指定该文件的名称和位置。可能很好,但是谁知道这是什么。人们使用“基于配置的约定”的口头禅来覆盖代码库中的许多错误决定,这让我很生气,因为他是事后来维护其文档不良的混乱,“可以正常工作”(但上帝禁止你改变任何东西-你将花费数小时来弄清楚如何破坏一切。
罗伯特·C·巴斯

3
@AidenStrydom我不同意。接受的答案实际上告诉我如何使用_ViewStart。这个答案只是谈论一个设计概念。我来这里是为了获得有关_ViewStart的信息,而不是获得有关Visual Studio为什么不告诉我有关_ViewStart的任何信息的信息。
米莉·史密斯

23

只是另一个想法。

如果您希望将自己的cshtml文件作为通用模板,则可以采用这种方式

_viewstart.cshtml您可以在其中提及您的通用cshtml文件。

@{Layout = "~/Views/Shared/_Layout.cshtml";}

14

源代码是比文档更好的地方。

参考Github 的MVC 6代码,我们有一些感兴趣的文件

----更新----

由于源结构的更改,有关如何收集viewstart页面的信息现在可以在RazorViewEngine.cs中找到,查找“ GetViewStartPages”函数。

---- /更新----

要回答它们如何发挥作用,请查看RazorView,我认为(由于IView)它与MVC管道相关。该文件具有RenderAsync方法,该方法从MVC管道中调用以呈现请求的视图。

RenderAsync调用RenderPage,然后调用RenderLayout(注意顺序)。RenderPage首先进行调用以处理viewstart文件(请注意,复数形式可能有多个_viewstart文件)。

因此,您可以从Microsoft.AspNet.Mvc.Razor命名空间下的RazorView.cs文件中的RenderViewStartAsync函数获取所需的信息。


7

这可能会立即向此问题添加一些其他信息(2016年MVC4,MVC5)。

Razor引擎会在_ViewStart.cshtml中找到并运行该代码,然后再在与_ViewStart.cshtml相同的目录或子目录中找到任何其他代码。

任何视图都可以覆盖Layout属性或其任何值。

只是想我可能会添加更多信息来向您展示为什么它是_ViewStart。

如果获得ILSpy并检查RazorViewEngine(System.Web.Mvc.dll)中的代码,您将看到代码本身引用了该名称。

_ViewStart在System.Web.Mvc.dll中

您会看到RazorViewEngine正在查找具有以下名称的文件:

razorviewengine代码

RazorViewEngine.ViewStartFileName = "_ViewStart";

3
这就是我一直在寻找的东西,我讨厌“不知道”我的项目正在发生什么,因为我也正在为VS做我自己的模板,而这个刚从空中出来的文件很难理解
Sebastian 506563

1

如果您希望页面具有通用布局,则需要定义通用布局并将视图与布局关联,我们必须在每个视图上都设置layout属性,这违反了DRY(请勿重复自己)原则。为此,.Net Framework提供了“ _ViewStart.cshtml”文件,该文件位于视图文件夹中。我们将布局信息放置在“ _ViewStart.cshtml”文件中,每个视图默认都使用此布局信息。如果要提供一些不同的布局信息,请假设您的主视图为您,可以参考该布局创建一个新的“ _ViewStart.cshtml”并将其放置在“主视图”文件夹中。


1

简短的答案是:呈现任何视图时,ViewStarts首先启动。长话如下:

创建单个视图文件的故事:

  1. ViewStart与ViewImports合并,然后作为一个文件执行。请注意,ViewImports始终与任何cshtml文件(包括ViewStart文件)合并。其目的是抽象@using语句和其他常见指令。
  2. ViewStart的输出(例如Layout和ViewData)可用于特定的View文件。
  3. 在View文件中,如果Layout变量为/变为null,则呈现视图的主体并将最终输出传递给用户。
  4. 如果Layout变量为/变为非null,则执行将移至布局文件,该文件又与ViewImports合并为单个文件,然后在布局文件内的@RenderBody()语句处将执行移回到视图文件它再次与ViewImports合并,并且输出与@RenderBody()位置处的布局文件合并,最终将最终输出传递给用户。

希望这使您知道程序生命周期中未知的谜团到底发生了什么。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.