This has been covered well in this Stackoverflow article but I was explaining the importance of the differences and of the implementation to a colleague recently.
The implementation is almost identical for each:
- Both require a configuration file;
- Logging objects in either are created in much the same way;
- Both have instance methods on a Logger object allowing you to log debug messages, warning messages errors etc.
private static Logger Log = LogManager.GetLogger(typeof(ThisClass));
public void SomeMethod()
// some code that may fail
Log.Error("SomeMethod() failed", ex);
The core difference for me though is that log4net is no longer being actively supported. It hasn’t been for years. I’ll admit, all my projects use log4net. Every one of them. But I’m considering changing.
NLog is current and seems to be moving with the goal posts and this gives me some comfort. The advantage that log4net offers is that the way I use it is so basic, i.e. class-level logging, I have to ask myself whether there is any point in changing?
The answer of course is to wrap the implementation of whichever logger is used in a facade pattern. This would allow you to use either as needs be.
I cam across this today and it bugged the hell out of me. I am using a custom ControllerFactory (kindly provided by Steve Sanderson’s awesome Pro ASP.NET MVC Framework) set in the global.asax.cs as such:
protected void Application_Start()
// Configure log4net
// Configure CastleWindsor
During the upgrade this stopped working and i started getting the following error:
System.MissingMethodException: No parameterless constructor defined for this object
I tracked the error down to the fact the constructors in my Controllers were not being initialized and I found the following quote from the breaking changes section of the What’s New in ASP.NET MVC 2:
“Custom controller factories are often used to provide dependency injection for ASP.NET MVC applications. To update the custom controller factories to support ASP.NET MVC 2, change the method signature or signatures to match the new signatures, and use the request context parameter instead of the property.”
After a little digging, the only change I needed to make was altering my custom ControllerFactory’s GetControllerInstance() override from:
protected override IController GetControllerInstance(Type controllerType)
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)