ASP.NET MVC Razor pass model to layout

What I see is a string Layout property. But how can I pass a model to layout explicitly?


  1. Add a property to your controller (or base controller) called MainLayoutViewModel (or whatever) with whatever type you would like to use.
  2. In the constructor of your controller (or base controller), instantiate the type and set it to the property.
  3. Set it to the ViewData field (or ViewBag)
  4. In the Layout page, cast that property to your type.

Example: Controller:

public class MyController : Controller
{
    public MainLayoutViewModel MainLayoutViewModel { get; set; }

    public MyController()
    {
        this.MainLayoutViewModel = new MainLayoutViewModel();//has property PageTitle
        this.MainLayoutViewModel.PageTitle = "my title";

        this.ViewData["MainLayoutViewModel"] = this.MainLayoutViewModel;
    }

}

Example top of Layout Page

@{
var viewModel = (MainLayoutViewModel)ViewBag.MainLayoutViewModel;
}

Now you can reference the variable 'viewModel' in your layout page with full access to the typed object.

I like this approach because it is the controller that controls the layout, while the individual page viewmodels remain layout agnostic.

Notes for MVC Core


Mvc Core appears to blow away the contents of ViewData/ViewBag upon calling each action the first time. What this means is that assigning ViewData in the constructor doesn't work. What does work, however, is using an IActionFilter and doing the exact same work in OnActionExecuting. Put MyActionFilter on your MyController.
public class MyActionFilter: Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            var myController= context.Controller as MyController;

            if (myController!= null)
            {
                myController.Layout = new MainLayoutViewModel
                {

                };

                myController.ViewBag.MainLayoutViewModel= myController.Layout;
            }
        }
    }

Seems like you have modeled your viewmodels a bit wrong if you have this problem.

Personally I would never type a layout page. But if you want to do that you should have a base viewmodel that your other viewmodels inherits from and type your layout to the base viewmodel and you pages to the specific once.