Anyone here have experience with custom error handling inside DNN 7?
The built in logging is fine, but my company has the need to extend DNN's built in error handling to include sending custom emails when ALL exceptions occur. We created a HttpModule that added an event listener on Application_Error, and have been emailing exceptions that way. However, after an exception is emailed, we are not being consistently redirected to the specified 500 Error page set in DNN's properties under Admin > Site Settings. We have different behavior depending on the exception type. Some exceptions (NullReferenceException) result in Application_Error firing and an email being sent but no redirection, others (HttpException) result in a redirect to the 500 page without the Application_Error event being fired. Is it possible something in DNN is catching these errors before Application_Error fires, and any ideas on how to fix these issues?
Here is the httpModule we added to the web.config:
/// /// Class for error handling and emailing exceptions to the error distribution list. /// public class ErrorModule : IHttpModule { #region Private Properties /// /// Gets the requested URL. /// /// The requested URL. private string requestedUrl { get { //TODO: create CmsPathTranslationFactory to create ICmsPathTranslator object for getting requested URL path return !string.IsNullOrEmpty(HttpContext.Current.Items["UrlRewrite:OriginalUrl"].ToString()) ? new Uri(HttpContext.Current.Items["UrlRewrite:OriginalUrl"].ToString()).AbsolutePath : HttpContext.Current.Request.Url.AbsolutePath; } } #endregion #region IHttpModule Members /// /// Initializes the specified application. /// /// The application. public void Init(HttpApplication application) { application.Error += new EventHandler(application_Error); } /// /// Disposes of the resources (other than memory) used by the module that implements . /// public void Dispose() { } #endregion #region Public Methods /// /// Handles the Error event of the application control. /// /// The source of the event. /// The instance containing the event data. public void application_Error(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; // get the last exception Exception exception = application.Server.GetLastError(); if (exception == null) { // exception is null, nothing to send sendErrorMessage(new Exception("Exception is null.")); return; } // get the inner exception if not null if (exception.InnerException != null) { exception = exception.InnerException; } if (exception is HttpException && ((HttpException)exception).GetHttpCode() == 404) { //don't send exception email for 404 } else { sendErrorMessage(exception); } } #endregion #region Private Methods /// /// Sends an email message with the specified error. /// /// The exception. private void sendErrorMessage(Exception ex) { using (MailMessage message = new MailMessage()) { message.To.Add(new MailAddress(ConfigurationManager.AppSettings["errorEmailToAddress"])); message.ReplyToList.Add(new MailAddress(ConfigurationManager.AppSettings["errorEmailReplyToAddress"])); message.From = new MailAddress(ConfigurationManager.AppSettings["errorEmailFromAddress"], Environment.MachineName); message.Subject = getErrorEmailSubject(ex, requestedUrl); message.Body = ex.ToString(); message.Priority = MailPriority.High; using (SmtpClient client = new SmtpClient()) { client.Host = ConfigurationManager.AppSettings["SMTPServer"]; client.Send(message); } } } /// /// Gets the error email subject based on the specified exception. /// /// The ex. /// The requested URL path. /// System.String. private string getErrorEmailSubject(Exception ex, string requestedPath) { return !string.IsNullOrEmpty(ex.Message) ? string.Concat(requestedPath, " - ", ex.Message) : requestedPath; } #endregion }