ASP.NET Core 2.1.0-preview1: Razor UI in class libraries

One frequently requested scenario that ASP.NET Core 2.1 improves is building UI in reusable class libraries. With ASP.NET Core 2.1 you can package your Razor views and pages (.cshtml files) along with your controllers, page models, and data models in reusable class libraries that can be packaged and shared. Apps can then include pre-built UI components by referencing these packages and customize the UI by overriding specific views and pages.

To try out building Razor UI in a class library first install the .NET Core SDK for 2.1.0-preview1.

Create an ASP.NET Core Web Application by running dotnet new razor or selecting the corresponding template in Visual Studio. The default template has fivestandard pages: Home, About, Contact, Error, and Privacy. Let’s move the Contact page into a class library. Add a .NET Standard class library to the solution and reference it from the ASP.NET Core Web Application.

We need to make some modifications to the class library .csproj file to enable Razor compilation. We need to set the RazorCompileOnBuild, IncludeContentInPack, and ResolvedRazorCompileToolset MSBuild properties as well as add the .cshtml files as content and also a package reference to Microsoft.AspNetCore.Mvc. Your class library project file should look like this:

ClassLibrary1.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <ResolvedRazorCompileToolset>RazorSdk</ResolvedRazorCompileToolset>
    <RazorCompileOnBuild>true</RazorCompileOnBuild>
    <IncludeContentInPack>false</IncludeContentInPack>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="Pages\**\*.cshtml" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.0-preview1-final" />
  </ItemGroup>

</Project>

For Preview1 making these project file modifications is a manual step, but in future previews we will provide a Razor MSBuild SDK (Microsoft.NET.Sdk.Razor) as well as project templates to handle these details for you.

Now we can add some Razor files to our class library. Add a Pages directory to the class library project and move over the Contact page along with its page model (Contact.cshtml, Contact.cshtml.cs) from the web app project. You’ll also need to move over _ViewImports.cshtml to get the necessary using statements.

Class library with Razor

Add some content to the Contact.cshtml file so you can tell it’s being used.

@page
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>

<h2>BTW, this is from a Class Library!</h2>

Run the app and browse to the Contact page.

Contact page from a class library

You can override views and pages from a class library in your app by putting the page or view at the same path in your app. For example, let’s add a _Message.cshtml partial view that gets called from the contact page.

In the class library project add a Shared folder under the Pages folder and add the following partial view:

_Message.cshtml

<h2>You can override me!</h2>

Then call the _Message partial from the contact page using the new partial tag helper.

Contact.cshtml

@page
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>

<h2>BTW, this is from a Class Library!</h2>

<partial name="_Message" />

Run the app to see that the partial is now rendered.

Contact page with partial

Now override the partial by adding a _Message.cshtml file to the web app under the /Pages/Shared folder.

_Message.cshtml

<h2>Overridden!</h2>

Rebuild and run the app to see the update.

Overridden partial

Summary

By compiling Razor views and pages into shareable libraries you can reuse existing UI with minimal effort. Please give this feature a try and let us know what you think on GitHub. Thanks!