92

I have the following project structure:

  • /Views/Shared/_Layout;

  • /Areas/Area1/Views/ControllerName/Index;

...

  • /Areas/AreaN/Views/ControllerName/Index.

Is there any way to force all areas to use the _Layout as a base layout?

Is there any way to do it without adding the _ViewStart file (for example, via the routing configuration)?

See Also:

How do I specify different Layouts in the ASP.NET MVC 3 razor ViewStart file?

Community
  • 1
  • 1
Mikhail
  • 9,186
  • 4
  • 33
  • 49
  • Here's a [one good answer](http://brockallen.com/2012/08/31/sharing-a-single-_viewstart-across-areas-in-asp-net-mvc/) and [another](http://stackoverflow.com/questions/4109205/how-do-i-use-a-common-viewstart-in-areas) – Rafael Emshoff Dec 15 '14 at 09:32

3 Answers3

162

You just have to add a file named:

_ViewStart.cshtml

Under each area views folder:

/Areas/Area1/Views/_ViewStart.cshtml

And edit the file to point to the root layout like this:

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

In order for this to work, you do not have to specify a value in the view's layout property, if you do, you would be overriding the global layout

Note: As Tony mentioned, you could edit each view's layout property to point to the root layout, however this is not the recommended way to do it since you would be coupling your views with your layout and change it would be painful

Edit 1

If you would like to use code to set the default view's layout, perhaps you should consider writing a custom view engine.

Try to google about custom RazorViewEngine and RazorView

This article could be a good start point

http://weblogs.asp.net/imranbaloch/archive/2011/06/27/view-engine-with-dynamic-view-location.aspx

I have not done something like this but I hope I'm pointing you in the right direction

Jupaol
  • 21,107
  • 8
  • 68
  • 100
  • 1
    Is there any way to do it without adding the "_ViewStart" file (for example, via the routing configuration)? – Mikhail Nov 07 '12 at 20:20
  • 2
    Within the routing I don't think so. They are two different things. Routing is in charge to try to match the current request URL with a route registered in the RoutesTable, when a match is found, an IMvcRouteHandler is created and then an IHttpHandler (MvcHandler) is in charge to process your controller's action. As you can see, this has nothing to do with views nor layouts. This is because a route doesn't necessary returns a view, it could return json or xml. So routing is not the correct place to implement something like this. – Jupaol Nov 07 '12 at 20:29
  • 1
    You can also add the `_ViewStart` directly in the Area folder directly to apply it to all areas. – Artur Jan 07 '20 at 21:45
21

Expanding on the answer by Jupaol....

At least in VS2013, the _ViewStart.cshtml file is added by default when creating the area, so it's already there, and you can change the contents as he notes to point to the root _Layout.cshtml. You can then remove the _Layout.cshtml in the area, since it is no longer used (and a potential source of confusion now)

However, by so doing any routing performed in that root _Layout.cshtml will need to consider areas.
The default _Layout.cshtml has a number of ActionLink helpers that need a slight modification:

Add the RouteValueDictionary param to any ActionLink calls by setting Area="". Note that empty string refers to the root level. This will allow these links to work correctly when invoked from within an area, still work when invoked from the root.

e.g.:

<li>@Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null)</li>
Rob Campbell
  • 451
  • 4
  • 10
3

You specify a layout using:

@{ Layout = "_Layout"; }

If you want to make this easier to change all at once. Perhaps you could just set it as a view bag variable and pass it in on the controller. To make it even easier you could create a base controller that the other controllers inherit from and have it assign the layout to the view bag there.

Not sure why routing would need to change or perhaps I am not understanding. Hope this helps :)

Tony
  • 3,269
  • 1
  • 27
  • 48