If you work Episerver in a digital agency, or, for a client who has different brands, a good goal to shoot for is to follow the DRY principle and be ruthless to the amount of duplicate code you write. If you're working on multiple Episerver projects and need to share code between them then a very common thought might be to create a custom shared code library (usually through a local NuGet feed on your build server).
This idea is good, however, when you come to try and log errors you hit a snag. Website A uses Episerver 7, which uses Log4NET version x and Website B uses Episerver 11 using Log4NET version. If you've ever stumbled onto this issue, then it can be a pain. In today's post, I'm going to give you my best tips on how you can tackle this problem, so let's get started.
How Can I Deal With Shared Code With Different Dependencies
If you want to create a shared code library, my advice is to figure this out before you start coding. From my experience there are a few main options to deal with logging:
- Use a third-party logging library, like NLog, that isn't being used by any project
- Write something custom
- A logging service
- Common.Logging with a custom Episerver log appender
Everyone will have their own preferences as to which approach they think better. Using something like NLog is probably the quickest and easiest. If you're using a service like Episerver DXC you may want to create your own logging server so you can get instant access to your logs.
On a recent project, we decided to try the 'common.logging' approach and for the remainder of this article, I'm going to cover my approach and my thoughts on it.
Implementing Common.Logging With Episerver
The Common.Logging provider was written to try and address exactly these type of issue. When you work on multiple projects, frameworks etc.. it is very common that different frameworks will use different logging providers or different versions. The Common.Logging library was developed to provide a simple abstraction to consumers of your code decide the type of logging implementation they want to choose. For reference, the Common.Logging Nuget package can be found here.
What this means is that in your shared code library, you install the Common.Logging provider. YIn this library ou use the common.logging log interface (very similar to the Log4Net one) to log your errors.
When you use that code in your Episerver website, you define some config in your web.config for the common.logger that defines the type of logging adaptor to use specific to that site.
When you use the common.logger, you don't define the logging framework in your shared library, you define one in each website that will consume it. What this means is that in each website that consumes your code, you will have a small amount of duplicate code that will define common logger for Episerver to use with common.logging.
This the decoupled the log provider from your shared code base, so now don't need to worry about DLL assembly mismatches. So the trace off of duplicate code in each solution means you can create a shared code library that will be easy to maintain and won't screw up your references in your web.config.
Implementing Common.Logging With Episerver
Admittedly all the info might be a little overwhelming to grasp at first (it was for me), so hopefully going over some code will make it a little easier.
This first bit of code defines a custom appender, the job of this class is to map the 'common.logging' interface to the Episerver logger.
You'll also need to create a factor adaptor. The adaptor is the thing that you point your common.logging settings within your web.config to, which looks like this:
The last thing is to add some 'common.logging' configuration within the web.config of each website that wants to consume your shared code, which looks like this:
That's it! Granted you need to copy these two files and add the config into each project that you want to consume your shared code library, but it does mean that any logs thrown in the shared code library will be logged within your Episerver logs AND you won't have any Nuget referencing hell with trying to include Log.
Common.Logging does provide a means to decouple a logging framework from your code. This can be handy if you want to have a shared code library that works between different websites. Granted the downside of this approach is that you need to add some custom code and some web.config tweaks into anything that you want to consume your shared codebase, however, from experience this is a good trade-off to get around the dependencies issues that can result.
Simply using third-party logging provide not used by EPiserverm like NLog would also get you around this problem. As Episerver doesn't use NLog, you'd never get the same assembly version conflicts if all your websites were using different versions of Episerver.
Using a sperate Log provide would mean that all your errors for the shared code would appear in a separate log file. As all the errors in that log would be generated by the shared code that isn't necessarily a bad thing depending on your situation.
I think my preference in most situations would be to lean towards NLog, as it's quicker, but using common.logging is also a good option.