.net, C# tip, Clean Code, Dependency Injection, Inversion of Control, MVC

How to use NLog or Serilog with C# in ASP.NET Core

ASP.NET core is still pretty new – at the time of writing, it’s still only at Release Candidate 1. I downloaded it for the first time a few days ago to play with the sample projects, and was surprised (in a good way) by how much has changed in the default project for MVC6. Of course the standard way of using Models, Views and Controllers is still similar to how it was in recent versions of MVC – but, the project infrastructure and configuration options are unrecognisably different (at least to me).

One of the first things I do when I set up a new project is configure the instrumentation – namely logging. I’d read a new feature of ASP.NET Core is that it provides built-in interfaces for logging – ILogger and ILoggerFactory.

This is a nice feature and provides me with an opportunity to write cleaner code. In previous versions of MVC, if I’d injected a logger interface into my controller classes, I still needed to introduce a dependency on a 3rd party library to every class that used this interface. So even though I’m injecting a dependency using an interface, if I changed logging library, I’d have to modify each of these classes anyway. Of course I could write a wrapper library for my 3rd party logging library, but I’d prefer not to have to write (and test) even more code.

Having the logging interface built into the framework gives me the opportunity to clean this up. So if I now want to add logging to my controller, I can write something like the code below. You can see this doesn’t have a dependency on a 3rd party library’s namespace – just a namespace provided by Microsoft.

using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.Logging;
 
namespace WebApplication.Controllers
{
    public class HomeController : Controller
    {
        private ILogger<HomeController> _logger;
 
        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }
 
        public IActionResult Index()
        {
            _logger.LogInformation("Home controller and Index action - logged");
            return View();
        }

For this post, I created a default MVC6 project, and modified the HomeController to match the code above – I just added the bold text.

So how can we integrate third party libraries into an MVC6 project?

Configure the default ASP.NET MVC6 project to use NLog

Let’s configure NLog first.

Install-package NLog.Extensions.Logging -pre
  • Then we need to add a configuration file – nlog.config – to the root of our project. You can get a perfect example from github here – just remember to change the file locations in this config file to directories that exist in your environment.
  • Finally, modify the Startup.cs file’s Configure method by adding a couple of lines of code.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddNLog();
    env.ConfigureNLog("nlog.config");

Now just run the project – notice I didn’t need to make any changes to my HomeController class. My project created a log file named “nlog-all-2016-03-27.log” which has the text:

2016-03-27 00:27:29.3796|WebApplication.Controllers.HomeController|INFO|Home controller and Index action - logged

Configure the default ASP.NET MVC6 project to use Serilog

Let’s say for whatever reason – maybe you want to use message templates to structure your logging data – you decide that you’d prefer to use the Serilog library instead of NLog. What changes do I need to make to my project to accommodate this?

Previously, if I’d wanted to change logging library, I’d have had to change every class that logged something – probably remove a namespace inclusion of “using NLog” and add a new one of “using Serilog”, and maybe even change the methods used to log information.

But with Asp.NET Core, I don’t need to worry about that.

  • First I need to install a pre-release nuget package for Serilog;
     Install-package Serilog.Sinks.File -pre
  • Next, I need to modify the Startup.cs file in a couple of places – the first change goes into the Startup method:
public Startup(IHostingEnvironment env)
{
    // For Serilog
    Log.Logger = new LoggerConfiguration()
        .WriteTo.File(@"C:\users\jeremy\Desktop\log.txt")
        .CreateLogger();

The next change goes into the Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddSerilog();

That’s it – after running the project again, I had logs written to the file at C:\users\jeremy\Desktop\log.txt, showing the entry:

2016-03-27 00:01:46.923 +00:00 [Information] Home controller and Index action - logged

Obviously I can also safely remove the NLog packages and configuration that this point.

Conclusion

So you can see the new ASP.NET Core framework has made it super easy to swap out logging library dependencies. A big advantage for me is that the logging interface used by each file is now part of the framework that Microsoft provide, which means my classes aren’t tightly coupled to an implementation.