Configuration ExceptionHandling without using an external configuration file

A couple of weeks ago, someone posted a question on the Enterprise Library GDN workspace, asking about how they could configure the Exception Handling block without using an external configuration file. I wrote a bit of code to do that, and I wanted to share it with everyone else.

Here is my solution. This first part is a very small change I made to ExceptionPolicy to allow it to accept an ExceptionPolicyFactory through an additional HandledException method.

//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Exception Handling Application Block
//===============================================================================
// Copyright © Microsoft Corporation. All rights reserved.
// Adapted from ACA.NET with permission from Avanade Inc.
// ACA.NET copyright © Avanade Inc. All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Properties;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Instrumentation;

namespace Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
{
    /// 
    /// Represents a policy with exception types and
    /// exception handlers. 
    /// 
    public static class ExceptionPolicy
    {
        private static readonly ExceptionPolicyFactory policyFactory = new ExceptionPolicyFactory();

        public static bool HandleException(Exception exceptionToHandle, string policyName)
        {
            return HandleException(exceptionToHandle, policyName, policyFactory);
        }

        public static bool HandleException(Exception exceptionToHandle, string policyName, ExceptionPolicyFactory factory)
        {
            if (exceptionToHandle == null) throw new ArgumentNullException("exceptionToHandle");
            if (factory == null) throw new ArgumentException("factory");
            if (string.IsNullOrEmpty(policyName)) throw new ArgumentException(Resources.ExceptionStringNullOrEmpty);

            ExceptionPolicyImpl policy = GetExceptionPolicy(exceptionToHandle, policyName, factory);

            return policy.HandleException(exceptionToHandle);
        }

        private static ExceptionPolicyImpl GetExceptionPolicy(Exception exception, string policyName, ExceptionPolicyFactory factory)
        {
            try
            {
                return factory.Create(policyName);
            }
            catch (ConfigurationErrorsException configurationException)
            {
                try
                {
                    DefaultExceptionHandlingEventLogger logger = EnterpriseLibraryFactory.BuildUp();
                    logger.LogConfigurationError(configurationException, policyName);
                }
                catch { }
                throw;
            }

            catch (Exception ex)
            {
                try
                {
                    string exceptionMessage = ExceptionUtility.FormatExceptionHandlingExceptionMessage(policyName, ex, null, exception);

                    DefaultExceptionHandlingEventLogger logger = EnterpriseLibraryFactory.BuildUp();
                    logger.LogInternalError(policyName, exceptionMessage);
                }
                catch { }

                throw new ExceptionHandlingException(ex.Message, ex);
            }
        }
    }
}

And here is an example I took from the ExceptionHandling basic quickstart. If you take this code and put it in the QuickStartForm.Main method and adjust the constructor for AppService to take an ExceptionPolicyFactory, then you should have a complete example. I’ve tried to indent the construction of the objects to make it more clear about what is being created and how it all gets hooked up.

[STAThread]
static void Main()
{
    DictionaryConfigurationSource internalConfigurationSource = new DictionaryConfigurationSource();
        ExceptionHandlingSettings settings = new ExceptionHandlingSettings();
            NamedElementCollection policyData = settings.ExceptionPolicies;
                ExceptionPolicyData globalPolicyData = new ExceptionPolicyData("Global Policy");
                    NamedElementCollection globalPolicyExceptionTypes = globalPolicyData.ExceptionTypes;
                        ExceptionTypeData exceptionType = new ExceptionTypeData("Exception", typeof(Exception), PostHandlingAction.None);
                            NameTypeConfigurationElementCollection exceptionTypeHandlers = exceptionType.ExceptionHandlers;
                            exceptionTypeHandlers.Add(new CustomHandlerData("Custom Handler", typeof(AppMessageExceptionHandler)));
                    globalPolicyExceptionTypes.Add(exceptionType);
                ExceptionPolicyData handleAndResumeData = new ExceptionPolicyData("Handle and Resume Policy");
                    NamedElementCollection handleAndResumeExceptionTypes = handleAndResumeData.ExceptionTypes;
                    handleAndResumeExceptionTypes.Add(exceptionType);
                ExceptionPolicyData propagatePolicyData = new ExceptionPolicyData("Propagate Policy");
                    NamedElementCollection propagatePolicyExceptionTypes = propagatePolicyData.ExceptionTypes;
                        ExceptionTypeData exceptionWithRethrowType = new ExceptionTypeData("Exception", typeof(Exception), PostHandlingAction.NotifyRethrow);
                    propagatePolicyExceptionTypes.Add(exceptionWithRethrowType);
                ExceptionPolicyData replacePolicyData = new ExceptionPolicyData("Replace Policy");
                    NamedElementCollection replacePolicyExceptionTypes = replacePolicyData.ExceptionTypes;
                        ExceptionTypeData securityExceptionType = new ExceptionTypeData("SecurityException", typeof(SecurityException), PostHandlingAction.ThrowNewException);
                            NameTypeConfigurationElementCollection securityExceptionTypeHandlers = securityExceptionType.ExceptionHandlers;
                            securityExceptionTypeHandlers.Add(new ReplaceHandlerData("Replace Handler", "Replaced Exception: User is not authorized to peform the requested action.", typeof(ApplicationException)));
                    replacePolicyExceptionTypes.Add(securityExceptionType);
                ExceptionPolicyData wrapPolicyData = new ExceptionPolicyData("Wrap Policy");
                    NamedElementCollection wrapPolicyExceptionTypes = wrapPolicyData.ExceptionTypes;
                        ExceptionTypeData dbConcurrencyExceptionType = new ExceptionTypeData("DBConcurrencyException", typeof(DBConcurrencyException), PostHandlingAction.ThrowNewException);
                            NameTypeConfigurationElementCollection dbConcurrencyExceptionTypeHandlers = dbConcurrencyExceptionType.ExceptionHandlers;
                            dbConcurrencyExceptionTypeHandlers.Add(new WrapHandlerData("Wrap Handler", "Wrapped Exception: A recoverable error occurred while attempting to access the database.", typeof(BusinessLayerException)));
                    wrapPolicyExceptionTypes.Add(dbConcurrencyExceptionType);
                  
                policyData.Add(globalPolicyData);
                policyData.Add(handleAndResumeData);
                policyData.Add(propagatePolicyData);
                policyData.Add(replacePolicyData);
                policyData.Add(wrapPolicyData);

        internalConfigurationSource.Add(ExceptionHandlingSettings.SectionName, settings);
        policyFactory = new ExceptionPolicyFactory(internalConfigurationSource);

    AppForm = new QuickStartForm();
    Application.Run(AppForm);
}

If this example isn’t clear to you, please let me know, and I can try to answer any questions that any of you may still have.
— bab
 

5 thoughts to “Configuration ExceptionHandling without using an external configuration file”

  1. Hi David,

    your post does programatically configure the logging application block and not the Exception Handling block. You are very active at the moment. If we advertise Entlib in our companies even more they will need Entlib Consultants 😉

    Yours,

    Alois Kraus

  2. Brian and Alois,

    I didn’t write that comment above. I guess someone read my post on the logging application block and confused that article with this post. Nice of them to mention my article, but I wish they would have used their own name 🙂

    I will be checking out this post soon, however, as I am very interested in the progammatic areas of Ent Lib.

    Regards,

    Dave

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.