Razor Class Libraries
I have been updating my Naif.Blog application to ASP.NET Core 2.1, and I noticed that when the site is published all the Razor cshtml files are “pre-compiled” into an assembly – [ProjectName].Views.dll (I noticed a similar behavior when using ASP.NET Core 2.0 – except that the assembly was named [ProjectName].PreCompiledViews.dll). This made me think - this could allow me to break the application into separate projects and I could deploy assemblies with embedded UI, thus allowing me to modularize the application. So I took a deeper look and realized that the ASP.NET Razor team have already thought about this and included a new Razor Class Library (RCL) feature into the 2.1 release.
So how do Razor Class Libraries work? Its actually quite simple. In this example I will be using Rider the awesome new IDE for C# from Jetbrains, but the process is similar when using Visual Studio. So first lets create a new Web Application – RCLApplication, using Rider’s New Solution option.
In the new Solution dialog, we will choose the Web App (MVC) option
This creates the default MVC Application with an About page, a Contacts page and a privacy page.
We can launch the Application and browse to the /Home/About page to confirm that we have a working application.
So now we have a working application lets modify it so that the About page is part of a Razor Class Library. We first need to create the project so we will use Rider’s Add project command. In the resulting dialog, we choose Razor Class Library for the Type and click the Create button.
The default project template for an RCL assumes that you are using MVC Areas.
The first thing we need to do is to create areference from the Application to the new Class Library.
Next lets move the “About” View from the Application to the Library. We start by removing the template files from the Library, and creating a Views folder and a Home folder. We then move the About Razor View file “About.cshtml” from the Application to the new Library.
And to prove that the View is being loaded from the Library, lets edit the markup in the View.
We can now build and run our application again and we will see that the new View is rendered from the Razor Class Library.
This works because we use the same “path” within the Razor Class Library as we used within the Application. What happens when both the Class Library and the Application have a Razor file at the same path. In this case ASP>NET Core renders the version in the application. We can prove this by creating a slightly different version of the Razor View in the Application.
When we build and run the application now the version from the Application is rendered.
While this was a fairly simple example, it does demonstrate the difficult part of modularizing an application, as we are now able to move our UI into a class library. By being able to add middleware, controllers, data models, view models and views in a single assembly we can acieve the vision of modularized ASP.NET MVC applications. I will be using this approach to move some of the theming aspects of Naif.Blog to a separate project to allow a good separation of “function” – the Blog engine and “content” – specific blog themes and components.