The whole purpose of MVC Turbine is to make the development of an MVC application easy and streamlined. This can be done through the use of a called “Blades”. Essentially, a Blade is nothing more than a component (or slice) of a Turbine application since it provides a layer of abstraction to a concern of the application. For example, a Turbine MVC application ships with three core blades out of the box:

  • MvcBlade – Performs all ASP.NET MVC related work, i.e., setup of Controller factories, View Engines, etc.
  • WebBlade – Performs all the ASP.NET related work, i.e., initialization of IHttpModules, etc.
  • RoutingBlade – Performs all the URL Routing related work, i.e., registers all routes within the application with the RouteTable.

The runtime allows a developer to define their own blades that suit the needs for their applications. In this blog post, we’ll examine a simple Logging Blade extension that uses log4net as the internal logger.

turbine_logging 

Logging Blade Internals

For the purpose of this blog post, I will use log4net as the underlying logging framework since it just works. For this example, I’ve made the decision that I want the logger for the application to be injected via the constructor of the components that need it.  Since everything in MVC Turbine is resolved from the IServiceLocator, the correct implementation of ILogger will be automatically injected.

The logger is defined as follows:

   1: public interface ILogger {
   2:     void LogMessage(string message);
   3:     void LogException(string message, Exception ex);
   4: }

Now, we can define the implementation to use the log4net.ILog as the internal log:

   1: internal class Logger : ILogger {
   2:     // Declare the log4net logger to use
   3:     private static readonly ILog log = LogManager.GetLogger(typeof(LoggingBlade));
   4:  
   5:    public ILog InternalLog {
   6:        get { return log; }
   7:    }
   8:  
   9:    public void LogMessage(string message) {
  10:        InternalLog.Debug(message);
  11:    }
  12:  
  13:    public void LogException(string message, Exception ex) {
  14:        InternalLog.Error(message, ex);
  15:    }
  16: }

The whole purpose of our ILogger implementation is to serve as a facade for the log4net logger. Now we wire up log4net to work with the web application, this is done via the LoggingBlade:

   1: public class LoggingBlade : Blade {
   2:     public override void Spin(IRotorContext context) {
   3:         // Register the log4net implementation of the logger
   4:         RegisterServices(context);
   5:  
   6:         // Setup log4net
   7:         SetupLogging();
   8:     }
   9:  
  10:     private static void RegisterServices(IRotorContext context) {
  11:         // This can live within a IServiceRegistration, but I opted to put here
  12:         // to keep the codebase small
  13:         context.ServiceLocator.Register<ILogger, Logger>();
  14:     }
  15:  
  16:     private static void SetupLogging() {
  17:         // Get the path to the file
  18:         string path = AppDomain.CurrentDomain.BaseDirectory;
  19:         string filePath = Path.Combine(path, "log4net.config");
  20:  
  21:         var fileInfo = new FileInfo(filePath);
  22:         if (fileInfo.Exists) {
  23:             // Get the info from the file
  24:             XmlConfigurator.ConfigureAndWatch(fileInfo);
  25:         }
  26:         else {
  27:             // Look at the web.config for the info
  28:             XmlConfigurator.Configure();
  29:         }
  30:     }
  31: }

The LoggingBlade does the following with log4net:

  • Registers our ILogger implementation with the IServiceLocator for the application.
  • Sets up log4net by either using a log4net.config file or the configuration section within web.config.

From here, MVC Turbine does the rest! At application start up, the MVC Turbine runtime will automatically call the LoggingBlade for us.

Application Usage

To use the Logging Blade within your application, all you need to do is reference it and apply the ILogger interface as needed. Here is how the HomeController uses the logger:

   1: public class HomeController : Controller {
   2:     // Inject the logger via ctor injection
   3:     public HomeController(IMessageService messageService, ILogger logger) {
   4:         MessageService = messageService;
   5:         Logger = logger;
   6:     }
   7:  
   8:     public IMessageService MessageService { get; private set; }
   9:     public ILogger Logger { get; private set; }
  10:  
  11:     public ActionResult Index() {
  12:         Logger.LogMessage("In the HomeController.Index method!");
  13:  
  14:         ViewData["Message"] = MessageService.GetWelcomeMessage();
  15:         return View();
  16:     }
  17:  
  18:     public ActionResult About() {
  19:         Logger.LogMessage("In the HomeController.About method!");
  20:  
  21:         ViewData["Message"] = MessageService.GetAboutMessage();
  22:         return View();
  23:     }
  24: }

The MessageService uses it too:

   1: public class MessageService : IMessageService {
   2:     
   3:     public MessageService(ILogger logger) {
   4:         Logger = logger;
   5:     }
   6:  
   7:     public ILogger Logger { get; private set; }
   8:  
   9:     public string GetWelcomeMessage() {
  10:         var message = "Welcome to ASP.NET MVC!";
  11:         Logger.LogMessage(string.Format("The welcome message is '{0}'", message));
  12:  
  13:         return message;
  14:     }
  15:  
  16:     public string GetAboutMessage() {
  17:         var message = "About ASP.NET MVC...";
  18:         Logger.LogMessage(string.Format("The about message is '{0}'", message));
  19:  
  20:         return message;
  21:     }
  22: }

When the application runs, it will now have logging support:

turbine_logApplication Log from the Logging Blade

Feel free to check out the source and see for yourself!

Happy Coding!