Best Practice for EL logging and exception handling in a web application

Topics: Exception Handling Application Block, Logging Application Block
Sep 21, 2012 at 4:40 PM

Hi all,  I am fairly new to EL and have been looking to no avail for best practices regarding using the EL Logging and Exception blocks with a Web application.  The web application that we have is ASP .Net 4.5, MVC 4.0 and has a very heavy javascript front end.  I am tasked with handling the logging and exceptions in a user friendly way and am wondering if there are best practices for this. 

I am thinking that I should probably consider doing the following.

Create the ExceptionManager and LoggingManager in the Global.asax.cs Application_Start method.  Create a fault contract to use with my RESTful service that is returning JSON data to the client.

Thanks

Sep 24, 2012 at 5:03 AM

Unfortunately, I don't think there are specific guidelines for different scenarios.  In general, Enterprise Library is trying to address best practices through reusable components & infrastructure.  The reason why there are not specific recommendations is that, like many things in software, the answer is: "it depends".

It depends on the overall application architecture and design and how you value certain application attributes (e.g. security, scalability, manageability, time, etc.).  It depends on potential, specific non-functional requirements of the application.  For example, I would say that logging is a best practice and, to that end, Enterprise Library provides a (very nice) means to achieve that.  That still leaves open the question of what to log, when to log, where to log, how configurable it should be, etc.

I guess the bad news is that Enterprise Library does not currently* have very tight integration with ASP.NET MVC.  For logging, always configure an error special source that writes to a location that has a high chance of success (e.g. a flat file trace listener to a directory that you know should have proper permissions).  This is so that errors while logging can be found and, if necessary, the log entries of the original request recovered.  Exception Shielding is always important but Enterprise Library does not have out of the box support for WebFaultException (which is what I would expect you to use for REST/JSON).  It doesn't totally apply but you could look at this for some Validation work to support WebFaultException: http://entlib.codeplex.com/discussions/392629.  A good article by Dino Esposito is ASP.NET MVC Tutorial: Handling Errors and Exceptions.

*Enterprise Library vNext is in planning stages so now is a good time to voice new ideas: http://entlib.uservoice.com/forums/89245-enterprise-library-6-0-unity-3-0.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Sep 25, 2012 at 3:29 PM

I am considering doing something like this -

    public class MvcApplication : System.Web.HttpApplication
    {
        public static IUnityContainer container;
        public static ExceptionManager exceptionManager;

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);                      

            // create the unity container and dependency objects
            container = new UnityContainer().AddNewExtension<EnterpriseLibraryCoreExtension>();
            exceptionManager = container.Resolve<ExceptionManager>();
        }
    }

I can use the UnityContainer 'container' elsewhere and the exceptionManager also.

Do you see any problems with this approach?

 

Sep 26, 2012 at 2:26 AM

I think this is an approach that will work.  I'm assuming you will use the container later to inject all dependencies at the request entry point (e.g. ControllerFactory).  If you are doing this you could forgo the ExceptionManager Field since that call also be resolved (and injected) when needed.  If the intent is to access the container as a service locator then you should know that's generally considered to be an anti-pattern.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

 

Sep 27, 2012 at 9:09 PM

Okay I am new to DI but do understand the benefits of using it or at least I thought I did.

If I understand you correctly in order to avoid setting up my DI container to not be like a service locator.  I need to do this at the ControllerFactory.  Here is the probelm that I have.  If I use constructor DI, how will that work since ASP.Net MVC is a framework and not a library?  What would be nice is if I could do something like this but I don't think the MVC framework will let me.  I am going to have to change the way the framework calls the factory and I am not sure if that is possible??  However if I could do this it will make my life a lot easier.

    public class HomeController : Controller
    {
        //
        // GET: /Home/

        private IRepository repository;

        public HomeController(IRepository repository)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("repository");
            }
            this.repository = repository;
        }
        ...
    }

 

Sep 27, 2012 at 9:19 PM

After discussing with another developer I think I just answered my own question.  Since it is obvious that the MVC is using a default ctor I can just create one and call my parameterised ctor there. 

Also if I make my param ctor public then I can call it with fakes which is great!!

I will try this and let you know.

Sep 27, 2012 at 11:52 PM

Okay here is what I cam up with.  First a note:  I made the parameterized ctor being called by the default ctor private because no one ele should ever call it or see it (this is a framework).  The other ctor which has the repository param is going to be called / setup via a fake, therefore a need to make it public.

Just curious, since this is a framework there should not be a problem with creating a singleton for some of my dependent objects should there be?

 

    public class HomeController : Controller
    {
        //
        // GET: /Home/

        // these are the dependency objects
        private LogWriter logger;
        private Repository.Repository repository;

        public HomeController()
            : this(
            MvcApplication.container.Resolve<Repository.Repository>(),
            MvcApplication.container.Resolve<LogWriter>())
        { }

        public HomeController(Repository.Repository repository)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("repository");
            }
            this.repository = repository;
        }

        private HomeController(Repository.Repository repository, LogWriter logger)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("repository");
            }
            this.repository = repository;

            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }
            this.logger = logger;
        }

        ...
    }
Sep 28, 2012 at 3:36 AM

You can definitely use singletons if they serve a purpose and work with your design.  Since you are using Unity, I would consider just creating a standard (threadsafe!) class and registering it with the container with ContainerControlledLifetime.  This ensures that the container will only ever instantiate one instance of the class and inject/resolve that instance as required.  This is what Enterprise Library does internally with the LogWriter implementation (LogWriterImpl) class.

If you use the 

 public HomeController(Repository.Repository repository)

constructor then you could end up with a null LogWriter which might cause issues.

The posted approach will work.  I would still consider having the controller's public constructor accept all required dependencies and have a higher level component (e.g. controller factory/dependency resolver) injecting those dependencies.  This would give the benefit of decoupling the controller from the Unity container as well as making it obvious what the controller's dependencies are.

Here's a ASP.NET MVC 4 article Test-Driving ASP.NET MVC.  Also worth reading: ASP.NET MVC 3 Service Location, Part 5: IDependencyResolver

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com