Where and how is the _ViewStart.cshtml layout file linked?

.Netasp.net Mvcasp.net Mvc-3Razor

.Net Problem Overview


Here's the About.cshtml from the default MVC 3 template:

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

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

I would expect that a reference to the _ViewStart file would be found in the About.cshtml, but clearly it's not.

I've looked in global.asax and web.config, but I can't find out how the About.cshtml file is "linked" with the layout from the _ViewStart file.

Everything works as expected, I'd just like to know what's going on under the hood...

.Net Solutions


Solution 1 - .Net

From ScottGu's blog:

> Starting with the ASP.NET MVC 3 Beta release, you can now add a file > called _ViewStart.cshtml (or _ViewStart.vbhtml for VB) underneath the > \Views folder of your project: > > The _ViewStart file can be used to define common view code that you > want to execute at the start of each View’s rendering. For example, > we could write code within our _ViewStart.cshtml file to > programmatically set the Layout property for each View to be the > SiteLayout.cshtml file by default: > > Because this code executes at the start of each View, we no longer > need to explicitly set the Layout in any of our individual view files > (except if we wanted to override the default value above). > > Important: Because the _ViewStart.cshtml allows us to write code, we > can optionally make our Layout selection logic richer than just a > basic property set. For example: we could vary the Layout template > that we use depending on what type of device is accessing the site – > and have a phone or tablet optimized layout for those devices, and a > desktop optimized layout for PCs/Laptops. Or if we were building a > CMS system or common shared app that is used across multiple customers > we could select different layouts to use depending on the customer (or > their role) when accessing the site. > > This enables a lot of UI flexibility. It also allows you to more > easily write view logic once, and avoid repeating it in multiple > places.

Also see this.

Solution 2 - .Net

In a more general sense this ability of MVC framework to "know" about _Viewstart.cshtml is called "Coding by convention".

> Convention over configuration (also known as coding by convention) is > a software design paradigm which seeks to decrease the number of > decisions that developers need to make, gaining simplicity, but not > necessarily losing flexibility. The phrase essentially means a > developer only needs to specify unconventional aspects of the > application. For example, if there's a class Sale in the model, the > corresponding table in the database is called “sales” by default. It > is only if one deviates from this convention, such as calling the > table “products_sold”, that one needs to write code regarding these > names.

Wikipedia

There's no magic to it. Its just been written into the core codebase of the MVC framework and is therefore something that MVC "knows" about. That why you don't find it in the .config files or elsewhere; it's actually in the MVC code. You can however override to alter or null out these conventions.

Solution 3 - .Net

Just another thought.

If you want to have your own cshtml file as a common template, you can do it this way

Within your _viewstart.cshtml you can mention your common cshtml file.

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

Solution 4 - .Net

The source code is a much better place to look for this than the documentation.

Referencing the MVC 6 code from Github, we have a few files of interest

----update----

Due to source structure changes, the information on how viewstart pages are gathered can now be found in RazorViewEngine.cs look for "GetViewStartPages" function.

----/update----

To answer how they come into play, look at RazorView, Which I believe (because of IView) is tied in to the MVC pipeline. This file has a RenderAsync method that gets called from the MVC pipeline to render the requested view.

RenderAsync makes calls to RenderPage AND THEN RenderLayout (NOTE THE ORDER). The RenderPage first makes calls to deal with viewstart files (note plural, there could be more than one _viewstart file).

So, the information you seek can be obtained from RenderViewStartAsync function in RazorView.cs file under Microsoft.AspNet.Mvc.Razor namespace.

Solution 5 - .Net

This may add some addt'l info to this question now (2016 ala MVC4, MVC5).

The Razor engine finds and runs the code in _ViewStart.cshtml before any other code which is in the same directory or subdirectory where the _ViewStart.cshtml is found.

Any view can override the Layout property or any of its values.

Just thought I might add a bit more info to show you why it is _ViewStart.

If you get ILSpy and examine the code in the RazorViewEngine (System.Web.Mvc.dll ) you will see that the code itself references that name.

_ViewStart in  System.Web.Mvc.dll

You can see that the RazorViewEngine looks for a file with that name:

razorviewengine code

RazorViewEngine.ViewStartFileName = "_ViewStart";

Solution 6 - .Net

If you want to have a common layout for your pages you need to define the common layout and to associate a view with layout we have to set layout property on each and every view, this violates the DRY(Don't Repeat Yourself) principle. For this .Net Framework has provide the "_ViewStart.cshtml" file, placed inside the view folder. We place layout information in "_ViewStart.cshtml" file and every view by default uses this layout information. If you want to give some different layout information, lets suppose to your Home view, you can create a new "_ViewStart.cshtml" with reference to that layout and place it in the "Home View" folder.

Solution 7 - .Net

The short answer is: ViewStarts start first when any view is being rendered. The long story is below:

The story of the creation of a single view file:

  1. The ViewStart is merged with ViewImports and then executed as a single file. Note that ViewImports is always merged with any cshtml file including the ViewStart file. Its purpose is to abstract @using statements and other common directives.
  2. The output of ViewStart (such as Layout and ViewData) becomes available to the specific View file.
  3. Inside the View file, if the Layout variable is/becomes null, the body of the view is rendered and the final output is delivered to the user.
  4. If the Layout variable is/becomes not null, the execution is moved to the layout file which in turn is merged with ViewImports as a single file and then at the @RenderBody() statement inside the layout file execution is moved back to the view file which is merges with ViewImports again and the output is merged with the layout file at the location of @RenderBody() and the final output is finally delivered to the user.

Hopes this makes you aware of what's really going on inside the unknown mysteries of your program's life cycle.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKmanView Question on Stackoverflow
Solution 1 - .Netjim tollanView Answer on Stackoverflow
Solution 2 - .NetrismView Answer on Stackoverflow
Solution 3 - .Netuser2515392View Answer on Stackoverflow
Solution 4 - .NetFrison AlexanderView Answer on Stackoverflow
Solution 5 - .NetraddevusView Answer on Stackoverflow
Solution 6 - .NetKamalDeepView Answer on Stackoverflow
Solution 7 - .NetShadi NamroutiView Answer on Stackoverflow