Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 902
SiberianGuy Avatar asked Nov 11 '10 12:11

SiberianGuy


People also ask

Can you mix MVC and Razor pages?

You can add support for Pages to any ASP.NET Core MVC app by simply adding a Pages folder and adding Razor Pages files to this folder.

What is _layout Cshtml in MVC?

The file "_Layout. cshtml" represents the layout of each page in the application. Right-click on the Shared folder in Solution Explorer then go to "Add" item and click on "View". Now the View has been created.


2 Answers

  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;             }         }     } 
like image 75
BlackjacketMack Avatar answered Sep 16 '22 18:09

BlackjacketMack


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.

like image 43
Mattias Jakobsson Avatar answered Sep 16 '22 18:09

Mattias Jakobsson