Step one - create my own controller class. Simple, just add a BaseController to the Controllers folder
public abstract class BaseController : Controller
{
}and then modify all existing contollers to inherit from BaseController rather than from System.Web.Mvc.Controller.
Next, I override the OnException method in the BaseController which is called whenever the exception is thrown within an action.
public abstract class BaseController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
var fileName = Path.Combine(Request.MapPath("~/App_Data"), "log.txt");
WriteLog(fileName, filterContext.Exception.ToString());
filterContext.ExceptionHandled = true;
this.View("Error").ExecuteResult(this.ControllerContext);
}
static void WriteLog(string logFile, string text)
{
StringBuilder message = new StringBuilder();
message.AppendLine(DateTime.Now.ToString());
message.AppendLine(text);
message.AppendLine("=========================================");
System.IO.File.AppendAllText(logFile, message.ToString());
}
}I can verify and find out that the Yellow Screen of Death is not indeed shown
Custom Error Page
And the log file is in my App_Data folder
Log File
Now that I can see it works, I would still want to see the exceptions as soon as they occur, rather than checking the log file on each occasion. To achieve that, first I need to add
<customErrors mode="RemoteOnly" />
to the system.web section of the Web.config file and then in the OnException method check if this section is set.
protected override void OnException(ExceptionContext filterContext)
{
var fileName = Path.Combine(Request.MapPath("~/App_Data"), "log.txt");
WriteLog(fileName, filterContext.Exception.ToString());
if (filterContext.HttpContext.IsCustomErrorEnabled)
{
filterContext.ExceptionHandled = true;
this.View("Error").ExecuteResult(this.ControllerContext);
}
}Finally, I would like to receive an email when something on my website goes wrong. I'm adding a function for that, rearranging a few lines and come up with the final version of my BaseController (for now).
using System;
using System.Web.Mvc;
using System.Text;
using System.IO;
using System.Net.Mail;
namespace Recipes.Controllers
{
public abstract class BaseController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
string ex = filterContext.Exception.ToString();
var fileName = Path.Combine(Request.MapPath("~/App_Data"), "log.txt");
WriteLog(fileName, ex);
SendEmail(ex);
if (filterContext.HttpContext.IsCustomErrorEnabled)
{
filterContext.ExceptionHandled = true;
this.View("Error").ExecuteResult(this.ControllerContext);
}
}
static StringBuilder ErrorText(string text)
{
StringBuilder message = new StringBuilder();
message.AppendLine(DateTime.Now.ToString());
message.AppendLine(text);
message.AppendLine("=========================================");
return message;
}
static void WriteLog(string logFile, string text)
{
System.IO.File.AppendAllText(logFile, ErrorText(text).ToString());
}
static void SendEmail(string text)
{
MailMessage mail = new MailMessage();
SmtpClient client = new SmtpClient("smtp.example.com");
client.Credentials = new System.Net.NetworkCredential("u$3r", "pa$$word"); client.Port = 587;
mail.From = new MailAddress("mvc@example.com");
mail.To.Add("developer@example.com");
mail.Subject = "Error on your website";
mail.Body = ErrorText(text).ToString();
client.Send(mail);
}
}
}References
Problem with generic base controller error handling in ASP.NET MVCASP.NET MVC HandleError Attribute, Custom Error Pages and Logging Exceptions
How to send email from Asp.net Mvc-3?
by Evgeny. Also posted on my website


No comments:
Post a Comment