322

I would like to have 2 separate Layouts in my application. Let's say one is for the Public section of the website and the other is for the Member side.

For simplicity, let's say all the logic for each of these sites is wrapped neatly into 2 distinct controllers.

  • PublicController
  • StaffController

And that they each have a corresponding Layout for all the View under each.

  • _PublicLayout.cshtml
  • _StaffLayout.cshtml

How do I use the _ViewStart.cshtml file to specify that all Views / Actions under "Public" use the PublicLayout and everything under "Staff" uses the StaffLayout?

InteXX
  • 5,804
  • 5
  • 33
  • 54
Justin
  • 10,107
  • 14
  • 56
  • 76
  • 4
    Just in case: if you want to remove the layout for a given `Razor` view, just set `Layout = null;` – Leniel Maccaferri Mar 19 '14 at 05:53
  • 3
    Just as a comment to your example, you should probably not have controllers named Public and Staff. Controllers are most often implemented as the entry point to CRUD-like action on certain key business entities, like EventController, UserController, or the like. If your application is reasonably big, the responsibility of a Public/Staff controller would be way to wide. Consider Areas instead. http://msdn.microsoft.com/en-us/library/ee671793%28VS.100%29.aspx You might be aware of this but someone else reading this might get the wrong idea, so just for the record. – Alex Jun 26 '14 at 17:08

3 Answers3

572

You could put a _ViewStart.cshtml file inside the /Views/Public folder which would override the default one in the /Views folder and specify the desired layout:

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

By analogy you could put another _ViewStart.cshtml file inside the /Views/Staff folder with:

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

You could also specify which layout should be used when returning a view inside a controller action but that's per action:

return View("Index", "~/Views/Shared/_StaffLayout.cshtml", someViewModel);

Yet another possibility is a custom action filter which would override the layout. As you can see many possibilities to achieve this. Up to you to choose which one fits best in your scenario.


UPDATE:

As requested in the comments section here's an example of an action filter which would choose a master page:

public class LayoutInjecterAttribute : ActionFilterAttribute
{
    private readonly string _masterName;
    public LayoutInjecterAttribute(string masterName)
    {
        _masterName = masterName;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        var result = filterContext.Result as ViewResult;
        if (result != null)
        {
            result.MasterName = _masterName;
        }
    }
}

and then decorate a controller or an action with this custom attribute specifying the layout you want:

[LayoutInjecter("_PublicLayout")]
public ActionResult Index()
{
    return View();
}
Darin Dimitrov
  • 960,118
  • 257
  • 3,196
  • 2,876
  • 1
    @DarinDimitrov Where I will create `LayoutInjecterAttribute`. ? Is there any particular location ? – kbvishnu Jul 18 '12 at 10:26
  • 2
    @VeeKeyBee, you could put it inside an `ActionFilters` sub-folder. – Darin Dimitrov Jul 18 '12 at 11:26
  • One potential problem with `LayoutInjecterAttribute`: It is called _before_ the controller's `OnException` method. So, if the controller provides a view result during exception handling, the layout won't be set. – Jeff Sharp Apr 21 '14 at 17:03
  • As a new guy to MVC, I would like to say thanks for teaching me alot in this answer. However I don't understand whats going on inside `OnActionExecuted`. Can you please update answer for me. – Imad Nov 24 '14 at 04:40
35

One more method is to Define the Layout inside the View:

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

More Ways to do, can be found here, hope this helps someone.

Shaiju T
  • 5,220
  • 15
  • 91
  • 175
  • 1
    This will not work - without the separate _ViewStart.cshtml, your view will still render inside the @RenderBody() method in the other layout. – Tillman32 Dec 05 '16 at 02:16
  • 1
    This! Why is everyone putting forward these extremely complex processes when all you need to do is this! – George Harnwell Feb 13 '18 at 16:54
17

This method is the simplest way for beginners to control Layouts rendering in your ASP.NET MVC application. We can identify the controller and render the Layouts as par controller, to do this we can write our code in _ViewStart file in the root directory of the Views folder. Following is an example shows how it can be done.

@{
    var controller = HttpContext.Current.Request.RequestContext.RouteData.Values["Controller"].ToString();
    string cLayout = "";

    if (controller == "Webmaster")
        cLayout = "~/Views/Shared/_WebmasterLayout.cshtml";
    else
        cLayout = "~/Views/Shared/_Layout.cshtml";

    Layout = cLayout;
}

Read Complete Article here "How to Render different Layout in ASP.NET MVC"

Mohsen Esmailpour
  • 9,428
  • 1
  • 37
  • 60
Anil Sharma
  • 608
  • 11
  • 12