[Source code: https://github.com/twlikol/TypedLayout]
Usually I use the path directly to specify the layout used by the current page.
But I really don’t like this way, I hope that I can apply the layout directly through the PageModel inherited by the page.
First I defined some Layout types, like:
namespace TypedLayout.Layouts
{
public abstract class HeaderAndFooterLayout<TModel> : Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>
{}
}Layout view:
@inherits TypedLayout.Layouts.HeaderAndFooterLayout<TModel>
@functions {
public static string Name
{
get { return "HeaderAndFooterLayout"; } }
}<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" /
<title>@ViewBag.Title</title>
</head>
<body>
<div style="border:1px solid #CCCCCC;">
This is HeaderAndFooter Layout.
</div>
<div>This is header</div>
<div>
@RenderBody()
</div>
<div>This is footer</div>
</body>
</html>
The next step is to define an custom PageModel:
namespace TypedLayout.Pages
{
public class HeaderAndFooterPageModel : PageModel
{}
}Next is the key part, I wrote a class called PageLayoutManager, injected in Starup.It has two important methods:
Initialize
Get all the current CompiledViewDescriptor from the ApplicationPartManager, and then identify whether it is a layout according to its BaseType, the base type is mapping to Layout types, if it is added to the temporary.
I additionally create an enum (PageKind)to do the mapping action. This will make this feature more flexible
GetLayout
Get the layout path according to the inherited custom PageModeltype.
In ViewStart, use it to get the Layout:
@using TypedLayout
@inject IPageLayoutManager pageLayoutManager
@{
Layout = pageLayoutManager.GetLayout(this.Model.GetType());
}Finally, I directly inherit my custom PageModel in my razor page.
namespace TypedLayout.Pages
{
public class IndexModel : HeaderAndFooterPageModel
{
public void OnGet()
{}
}
}[Source code: https://github.com/twlikol/TypedLayout]
