This post is a continuation of the Evolving ASP.NET series:
In the second post in this series we took a close look at the source code for BugTracker.NET. We found a number of issues ranging from security problems to out of date third party libraries to the lack of proper directory structure.
In this post and the few that follow we will explore how to deal with references to older 3rd party packages. It is worth reviewing each of these packages to check for the following:
- Is there a newer version of the package available? Older versions may no longer be supported, or in the case of some web frameworks they may not work in new browsers.
- Is the package available on Nuget? Pulling from Nuget will save a lot of time for future updates.
- Are there better options for the packages? It is possible that the package has been superseded by some newer and better tool.
In BugTracker.NET, we have identified 3 different .NET packages that were being referenced: log4net, Lucene.NET and SharpMimeTools.
Log4net is a logging framework that provides a wrapper to various different logging mechanisms. It is a very commonly used framework that is not updated particularly frequently.
Lucene.NET is a full text search engine. You can insert records into it and then have Lucene return the matching documents. Lucene is actually is the foundational technology behind Elastic Search as well as Solr.
Finally the SharpMimeTools library provides the ability to read and decode MIME messages. This is the encoding used in e-mail attachments. In BugTracker.NET it is used to allow reading e-mails sent to open bugs.
All appear to be very out-of-date. We'll take a look at each one of these to see what options we might have to replace them.
In this post, we’ll limit ourselves to updating log4net to the latest. Correcting all dependencies is too long for a single post.
BugTracker is referencing v1.1.4322 of log4net. The current supported version of log4net is v1.2.13 and it is available on Nuget. Upon reviewing the release notes, we can see that there are a large number of bug fixes between v1.1.4322 and v1.2.13. Unfortunately, there are also a number of breaking changes in the v1.2 release. We will need to review how BugTracker is using log4net to assess the difficulty of upgrading to the latest.
To our surprise, BugTracker is referencing the log4net package but never actually uses the log4net. After doing a little digging, we see some custom logging code in Global.asax:
There are definitely problems with this code. There is one other method in util.cs that does some logging. This method is overly complex and definitely needs some fixing. Rather than try to fix these methods, we are going to replace the custom logging code with a standard .NET logging package.
Choosing a Framework
The 2 most common logging frameworks in .NET are log4net and NLog. Both are acceptable choices and we won't get into the details of comparing the 2 frameworks. We are going to move forward with NLog as it is a little newer and seems to have a more active community.
First, we need to remove the reference to the old log4net assembly and delete the file from the references folder. Now we can add a reference to the latest version of NLog using the Nuget Pacakge Manager Console (Tools -> Nuget Package Manager -> Package Manager Console).
Next, we need to configure NLog. This can be done using xml configuration files, which is very flexible but also a little messy. Since we are only looking for very basic file logging to replace the existing logging functionality, we would prefer to configure logging programatically in C#.
Let's start by creating a App_Start folder that will contain classes that are used to configure components of the application when it starts up. This is a pattern that is used in newer ASP.NET applications and can be seen when creating a new ASP.NET application in Visual Studio 2013.
In the startup folder, we will create a static LogConfig class that will contain a static Configure method with all our log4net configuration.
In Global.asax.cs, call the logging configuration method in the Application_OnStart method:
Replacing Custom Logging Code
Now that NLog is configured, we can start replacing the old custom logging code.
Starting with the code in Global.asax.cs, replace the logging code with the new NLog logging code:
Resolving Relative Paths
While testing this change, we appear to have encountered our first yak that requires some shaving.
The call to Util.get_log_folder() in LoggingConfig.Configure fails because of the weird way the application is attempting to resolve relative paths using some value that is cached in the HttpRuntime. Let's simplify this approach by using a more standard and fail-safe method of resolving relative paths.
Now that the error logging is working as expected, let's replace the code in Util.write_to_log with the following simplified logging code:
We can delete the method Util.get_log_file_path since it is no longer used.
There is a large block of code in Global.asax.cs that deals with sending out email notifications where unhandled exceptions occur. This logic is easily replaced using the Mail Target in NLog. By adding the following code to the LoggingConfig.Configure() method, we can delete all the custom email logic.
Again, we were able to reuse the existing settings in Web.config to configure NLog.
We have now replaced all the custom logging code in BugTracker with a very popular and well supported open source logging framework.