ASP.NET MVC Razor Pass Model to Layout

ASP.NET MVC Razor pass model to 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.

Mvc5 pass model to Layout Page

Looks like a good usecase to use a ChildAction which can be called from the layout view.

So start by creating a view model to represent the data

public class AlertVm
{
public int EmailCount { set; get; }
public int NotificationCount { set; get; }
}

Now create an action method which creates an object of this, set the values and pass to a partial view

[ChildActionOnly]
public ActionResult Alerts()
{
var vm = new AlertVm {EmailCount = 4, NotificationCount = 2};
return PartialView(vm);
}

Now your Alerts.cshtml view, which is strongly typed to our view model, you can render whatever you want.

<div>
<p>@Model.EmailCount emails</p>
<p>@Model.NotificationCount notifications</p>
</div>

And this action method can be invoked from the _Layout.cshtml view.

<div>@Html.Action("Alerts", "Home")</div>

With this approach, you do not need worry about the creating a view model for every single action. (Ex : Your about page which does not need a view model usually)

Pass Model into Layout Page MVC

you have to create a base view model that you will have to use for ALL your views

using Microsoft.AspNetCore.Mvc.Rendering;

public interface IBaseViewModel
{
public int CategoryId { get; set; }
public List<SelectListItem> CategoryList { get; set; }
}

public class BaseViewModel : IBaseViewModel
{
public int CategoryId { get; set; }
public List<SelectListItem> CategoryList { get; set; }
}

action

public IActionResult Index()
{

var baseViewModel=new BaseViewModel();
InitBaseViewModel(baseViewModel);
return View(baseViewModel);
}

private void InitBaseViewModel(IBaseViewModel baseViewModel)
{

//this is for test
// in the real code you can use context.Categories.Select ....

var items = new List<SelectListItem> {
new SelectListItem {Text = "Category1", Value = "1"},
new SelectListItem {Text = "Category2", Value = "2"},
new SelectListItem {Text = "Category3", Value = "3"}
};

baseViewModel.CategoryList= items;
}

layout

@model IBaseViewModel // you can omit it but I like to have it explicitly

@if(Model!=null && Model.CategoryList!=null && Model.CategoryList.Count > 0)
{
<select class="form-control" style="width:450px" asp-for="CategoryId" asp-items="CategoryList">
}

for another view you can create this action code

public IActionResult MyAction()
var myActionViewModel= new MyActionViewModel {
..... your init code
}

InitBaseViewModel(myActionViewModel);

return View(myActionViewModel)
}

public class MyActionViewModel : BaseViewModel
//or
public class MyActionViewModel : IBaseViewModel
{
public .... {get; set;}
}

Passing model to _Layout.cshtml (webapp version)

I don't know how I didn't think of it before. It's a simple inheritance with PageModel and your bound attributes is available in your _layout and in your final page. No need to create the view or to use a generic as with the MVC framework.

Here it is the very simple solution :)

Thanks to those who spent time searching

Pass data to layout that are common to all pages

If you are required to pass the same properties to each page, then creating a base viewmodel that is used by all your view models would be wise. Your layout page can then take this base model.

If there is logic required behind this data, then this should be put into a base controller that is used by all your controllers.

There are a lot of things you could do, the important approach being not to repeat the same code in multiple places.

Edit: Update from comments below

Here is a simple example to demonstrate the concept.

Create a base view model that all view models will inherit from.

public abstract class ViewModelBase
{
public string Name { get; set; }
}

public class HomeViewModel : ViewModelBase
{
}

Your layout page can take this as it's model.

@model ViewModelBase
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
</head>
<body>
<header>
Hello @Model.Name
</header>
<div>
@this.RenderBody()
</div>
</body>
</html>

Finally set the data in the action method.

public class HomeController
{
public ActionResult Index()
{
return this.View(new HomeViewModel { Name = "Bacon" });
}
}


Related Topics



Leave a reply



Submit