Reuse UI with Razor Class Libraries (RCL) in ASP.NET Core
Developers always look for ways to reuse their code and markup. ASP.NET Core
offers several ways to reuse code and markup within a project (partials, custom
tag helpers, view components etc.). What if you want to reuse a piece of user
interface (UI) across multiple web applications? Luckily, ASP.NET Core 2.1
introduced what is known as Razor Class Library (RCL) projects that can be used
to accomplish this task.
Simply put, RCL is a collection of view models, controllers, views, layouts,
and partials that you want to reuse across multiple applications. RCL also
allows you to isolate pieces of UI from your web application. Of course, you
don't need to put all these pieces into RCL. For example, you may want to
isolate only views and partials into RCL and not the controllers. It's up to you
as a developer to decide what and how you would like to reuse the UI.
In order to create a new RCL, Visual Studio provides a project template as
shown below :
As you can see, the ASP.NET Core 2.1 includes Razor Class Library project
template. The resultant project is similar to a normal class library but uses
Razor SDK. The default RCL project assumes that you are going to use ASP.NET
Core Areas to organize your applications. By default it is also assumed that you
are using Razor Pages. However, you are not bound by these defaults. In the
example that follows we will be using ASP.NET Core MVC organized into typical
folder structure (we won't use areas).
The following figure shows how our view models, views, and controllers can be
organized.
As you can see we have created the typical MVC folder structure inside the
RCL project. Let's summarize this file organization for the sake of clarity :
- Controllers folder contains one or more controllers that you want to
reuse. In this case we want to reuse HomeController.
- The ViewModels folder contains view models (you can call it just Models
if you so wish) and contains Employee view model class.
- The Views folder contains _ViewImports and _ViewStart files.
- The Views > Home folder contains Index view.
- The Views > Shared folder contains layouts and partials shared by the
views.
Ok. Begin by creating a new RCL and also add the ViewModels, Views, and
Controllers folders.
The Employee view model class is shown below:
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then add _Layout.cshtml to the Views folder and write the following markup in
it :
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<h1>Welcome to RCL!</h1>
<hr />
<div>
@RenderBody()
</div>
</body>
</html>
Then add _Partials.cshtml file and modify it a shown below :
<h2>@ViewBag.Message</h2>
It simply outputs Message ViewBag property. The Message property is set by
the HomeController.
Then add _ViewStart.cshtml and _ViewImports.cshtml files as shown below :
@{
Layout = "_Layout";
}
And
@using RCL.ViewModels;
@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers
Now add Index.cshtml and modify it as shown below :
@model Employee
<h1>RCL - @ViewBag.Title</h1>
<h3>
@Html.DisplayForModel()
</h3>
<hr />
<partial name="_Partial" />
As you can see, we simply output the Employee model data using the
DisplayForModel() method. We also render the _Partial using the <partial> tag
helper.
Finally, add HomeController and write its Index() action as follows :
public IActionResult Index()
{
Employee emp = new Employee()
{
EmployeeID = 1,
FirstName = "Nancy",
LastName = "Davolio"
};
ViewBag.Title = "Employee Details";
ViewBag.Message = $"Last updated on
{DateTime.Now.ToShortDateString()}";
return View(emp);
}
The Index() action prepares an Employee model object. It also sets Title and
Message ViewBag properties.
This completes the RCL code.
Next, add an ASP.NET Core web application project to the same solution.
Then add a reference to the RCL library you just created using the Add
Reference dialog :
After adding the project reference of the RCL project the web application
looks like this :
The web application doesn't have any view model, controller, or views. Press
F5 to run the application. If all goes well your browser should resemble this :
As you can see, the view model, views, partial, layout - all has been
correctly picked from the RCL.
Overriding the views
If you wish you can also override the views, partials, and layouts provided
by the RCL by adding them in the web application. Consider the following :
Here, we added Views folder to the web application. The Views folder has its
own Index.cshtml, _Layout.cshtml, and _Partial.cshtml. Since the web application
has its own razor code files they will be used instead of what is available in
the RCL.
A sample run of the above web application confirms this :
As you can see from the page title, heading and partial, RCL implementation
is now overridden by web application's implementation.
If you wish you can put only *.cshtml files in the RCL and keep controllers
and view models in the web application project.
That's it for now! Keep coding!!