Razor Class Library with ASP.NET Core MVC


Razor Class Library with ASP.NET Core MVC

ASP.NET Core 2.1 introduces Razor Class Library (RCL) . It’s the new way how to share reusable web application components with UI as dependent project or NuGet package. As public examples mostly cover how it works with Razor Pages, I decided to write this blog post and demo application for ASP.NET Core MVC.

Source code available!I created demo application that shows all stuff written here. Feel free to visit my GitHub repository gpeipman/RazorClassLibraryDemo . To make it work it’s important to have stable release of .NET Core 2.1 without any preview or release candidate releases.

What is Razor Class Library?

Razor Class Library is ASP.NET Core library that contains pages, views, view components and other web application artifacts with their respective code. Library doesn’t run independent – there must be application that includes library and uses its functionalities. Razor class libraries make it easy to share web applications code with UI elements.

Razor class libraries doesn’t work well on preview and release candidate versions of ASP.NET Core 2.1.

Razor class libraries are similar to ASP.NET Core web applications by structure. It is recommended to put custom UI pieces to areas and it is up to developers to make sure that the names of areas doesn’t match.

Screenshot on right shows default structure. For some reason the project comes with Razor page. There is nothing about MVC and there’s also no project template for Razor class library with MVC structure.

But MVC is actually supported and it’s up to us to build the project structure we need.

Referencing Razor class library

There are two ways to reference Razor class library:

  • Project reference
  • NuGet package

If class library is in same solution with web application then project reference is enough.

Another important dependency is project dependency under build dependencies menu (right click on web application and select Build dependencies).

Setting this dependency tells Visual Studio that library project must be built before web application one.

Moving to MVC

Now we have everything prepared and it’s time to move to MVC. Screenshot on right shows the minimal structure we need to get things running. From MyFeature folder remove all Razor pages things that were created automatically and create simple MVC folder structure with HomeController and Index view.

There are some things to know:

  • Controllers must have AreaAttribute
  • Web application must have area route defined

Now let’s implement these changes and let’s make things work.

We start with HomeController in library project. I started with minimal and extremely primitive code.

public class HomeController : Controller
    public IActionResult Index()
        return View();

Same goes for Index view of HomeController.

Hello from MyFeature

In Startup class of web application include MVC like show here (Configure method).

app.UseMvc(routes =>
    routes.MapRoute("areas", "{area}/{controller=Home}/{action=Index}/{id?}");
    routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

Now we are ready to run our application and try out view from Razor class library.

Hold on, what the hell is this? Well… we have area defined in another project and what’s going on in web application doesn’t apply to it fully. We need to copy _ViewStart.cshtml file under Shared folder in Razor class library. After this things get better.

This is the easiest method to use and it works well for applications with only one layout.

Overriding Razor class library views

It’s possible we want to use our own view instead of one that comes with Razor classlibrary.

For this we need to build exactly the same area structure as we built in Razor class library but we build it in our web application. We don’t need any copies of controllers or models in Razor class library project, just views we need to override.

It’s possible to override also controllers the same way but this is more complex topic and it needs some good analyzis before doing so. The question comes down to simple thing – is library author expecting something like this to happen?

Image on right shows how I replicated areas structure in Razor class library above to web application. Notice how there is only the index view of HomeController that I want to override.

Here is the primitive content of overriden view.

Hello from overridden MyFeature

And here is our overridden view in action.

If needed we can override views but we have to be careful – views from Razor class library may contain logic we don’t know.

Wrapping up

Razor Class Library is excellent way how to share web application components and UI artifacts. It’s not just about sharing components between projects in same solution – we can share our Razor class libraries as NuGet packages. The model seems flexible enough for me as it easy to take risks of overriding controllers, models, views and other components. I don’t give any suggestion right now about overriding as I am not yet sure what weight it actually puts to those responsible of Razor class libraries. Anyway, with Razor class libraries one problem is solved again.

Writing Tests for Apollo Client in React





Razor Class Library with ASP.NET Core MVC