In an earlier post in this series I blogged about creating themes for my blogs. In my most recent updates I have added support for pages to my blog. All the pages on the site are rendered with the same View Page view, so would therefore use the same layout or “template”. Even in a fairly simple site this quite restrictive, and in the post I will show how you can support multiple different layout pages or page templates.
The layout for an MVC view is determined by the Layout property, which is set – most of the time – in the _ViewStart.cshtml file.
The _ViewStart view executes before any View. However, we can override the setting of the Layout property at the top of any view. Lets look at our updated ViewPage view in the gist below.
In this code we can see that the Layout property is updated if the Page model’s PageTemplate property is not null or empty. I have chosen to place all the page templates in a Templates folder of the blog’s Theme.
In the edit screen for a page the Page Template can be chosen from a list of available templates.
But how do you actually get a list of themes. In Development mode the Views are loaded and compiled at runtime but the default for Production is to compile the views into an assembly as part of the Publish step. Thankfully the Razor View Engine exposes the methods it uses internally to locate views. ASP.NET Core provides an IFileProvider interface and a couple of implementations PhysicalFileProvider (that is used to locate views in the physical file system) and EmbeddedFileProvider, which is used to locate compiled views in an assembly. So we don’t really need to know whether the views are compiled or not. We can use the IFileProvider interface to parse all the FileProviders for our page templates(see gist below)
Note: This is the theory. When I tried this in production the Views were not returned, so I have instead updated the project settings to compile the Views when publishing the project.
The source for Naif.Blog can be found at https://github.com/cnurse/Naif.Blog. If you want to find the state of the repository used in this post then you can find that at the tagged release v0.7.0 (https://github.com/cnurse/Naif.Blog/releases/tag/v0.7.0)