This post will describe how to share controllers and views across ASP.NET Core applications, shared via an ASP.NET Core library.

Best practices within the model-view-controller (MVC) world dictate that we should keep our controllers as thin as possible. Controllers should be extracted away from business logic, operational logic, and any sort of decision making. The only real thing controllers should be doing, are acting as a bridge. A bridge from the http world, to the domain logic of an application.

There is sometimes the case where the controllers themselves might want to be reused across applications. Perhaps you are creating an eCommerce framework, where a product catalog REST API needs to work out of the box. Or maybe there is a need to have similar controllers working together in multiple processes, based on the same controller code, but change of behaviour through configuration. It would be very handy to be able to reuse Controllers and View logic.

Adding controllers to a library

Controllers themselves are just C# classes. They can live within any type of .NET class library. However, to enable their use within an application, you need to register such controllers against the ASP.NET core application model.

// This will retrieve the assembly for your custom library.
var assembly = typeof(ControllerInLibrary).GetTypeInfo().Assembly; 

// This will add the assembly as an application part. ASP.NET Core will then find controllers within it.
services.AddMvc()
        .AddApplicationPart(assembly)

Once this is done, the ASP.NET Core engine will pick up these controllers, registering them for use against the current application.

Adding Views to a library

Sometimes your controllers will also have default views within the .NET library as well. These can be placed within the library, and added as an embedded resource.

<ItemGroup>
    <EmbeddedResource Include="Views\**\*.cshtml" /> 
</ItemGroup> 

Once they are added as a resource, you can then augment the razor view options on startup of your application, to include the views from this assembly:

// Add views provided in this assembly.
services.Configure<RazorViewEngineOptions>(options =>
{
    options.FileProviders.Add( 
        new EmbeddedFileProvider(typeof(ControllerInLibrary).GetTypeInfo().Assembly)); 
});

Summary

From this short post, I have described potential reasons why you may want to share controllers and views across applications. I have also shown how easy it is, with very little code, to augment your applications to take advantage of your new custom library of controllers.

Thanks for reading and I hope this helps you.