ASP.NET WebPages - Application Error Handling

There are many ways in which you can handle and log errors in your application. This tutorial will show you how to log errors in ASP.NET using XML files. This example is for ASP.NET WebPages developers, but can be easily migrated to Web Forms and MVC.

Getting Started

In your website add a Global.asax file if you do not already have one. The Global.asax file has a few methods, but we are only interested in this method:

Sponsored Links
void Application_Error(object sender, EventArgs e)
{

}

This method is executed when an error occurs in our site. This is how the process works: when an error occurs we create an XML file in the App_Data folder with the name ErrorLog-DATE.xml. This file will contain all the error details. If the file exists, then we simply edit the file and add the new error.

Under the Application_Error method add the following method:

void LogError(Exception ex, string LogFile)
{

}

Inside the above method add this code:

if (!File.Exists(LogFile))
        {

            XmlWriterSettings settings = new XmlWriterSettings();

            settings.CheckCharacters = false;
            settings.Indent = true;

            using (XmlWriter writer = XmlWriter.Create(LogFile, settings))
            {

                if (ex.Message != null)
                {

                    writer.WriteStartDocument();
                    writer.WriteStartElement("Errors");
                    writer.WriteStartElement("Error");

                    writer.WriteElementString("ErrorMessage", ex.Message);

                    if (ex.InnerException != null)
                    {
                        writer.WriteElementString("InnerException", ex.InnerException.ToString());
                    }

                    writer.WriteElementString("URL", Request.Url.AbsoluteUri);

                    if (Request.UrlReferrer != null)
                    {
                        writer.WriteElementString("Refer", Request.UrlReferrer.ToString());
                    }

                    writer.WriteElementString("IPAddress", Request.UserHostAddress);
                    writer.WriteElementString("Source", ex.Source);
                    writer.WriteElementString("DateTime", DateTime.UtcNow.ToString());
                    writer.WriteEndElement();//End Error  
                    writer.WriteEndElement();//End Errors
                    writer.WriteEndDocument();
                    writer.Flush();
                    writer.Close();
                }

            }

}

This is the first phase; if the file does not exist then we go ahead and write a new XML document. Notice how we collect a few details about the error, including refer URL, the URL where the error occurred, the IP address, and of course the error itself. You could collect more information if you like, such as the browser. Under the last brace add the next part:

else
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(LogFile);

            //CREATE ROOT NODE 
            XmlElement element = doc.CreateElement("Error");

            XmlElement ErrorMessage = doc.CreateElement("ErrorMessage");
            ErrorMessage.InnerText = ex.Message;

            XmlElement URL = doc.CreateElement("URL");
            URL.InnerText = Request.Url.AbsoluteUri;

            XmlElement IPAddress = doc.CreateElement("IPAddress");
            IPAddress.InnerText = Request.UserHostAddress;

            XmlElement Source = doc.CreateElement("Source");
            Source.InnerText = ex.Source;

            XmlElement ErrorDateTime = doc.CreateElement("DateTime");
            ErrorDateTime.InnerText = DateTime.UtcNow.ToString();

            XmlElement InnerException = doc.CreateElement("InnerException");
            XmlElement URLRefer = doc.CreateElement("Refer");

            element.AppendChild(ErrorMessage);
            if (ex.InnerException != null)
            {

                InnerException.InnerText = ex.InnerException.ToString();
                element.AppendChild(InnerException);
            }
            element.AppendChild(Source);
            element.AppendChild(URL);
            if (Request.UrlReferrer != null)
            {
                URLRefer.InnerText = Request.UrlReferrer.ToString();
                element.AppendChild(URLRefer);
            }
            element.AppendChild(IPAddress);
            element.AppendChild(ErrorDateTime);

            doc.DocumentElement.AppendChild(element);
            doc.Save(LogFile);            
        }

This is similar to the previous example except we use the XmlDocument and XmlElement to append to the XML file. Here we have only created the method we need to call this method. In the Application_Error, add the following:

//Get the error details
        HttpException ex = Server.GetLastError() as HttpException;

        string FileName = "ErrorLog-" + DateTime.Now.ToString("dd-MMM-yyyy") + ".xml";

        string LogFile = Server.MapPath("~/App_Data/" + FileName);

        if (ex.InnerException != null)
        {
            if (ex.InnerException.Message.Contains("A potentially dangerous Request"))
            {
                Response.Redirect("~/error/xss");
            }
            else
            {
                LogError(ex, LogFile);
            }
        }
        else if (ex.Message.Contains("A potentially dangerous Request"))
        {
            Response.Redirect("~/error/xss");
        }
        else
        {
            LogError(ex, LogFile);
        }

There are a few things to take note of here. Firstly, the filename follows a certain format, ErrorLog-DATE.xml, so it might be ErrorLog-14-Jun-2014. It's best to make a file for each day.The log file is stored in the App_Data folder, which is recommended as it's a secure location. Now the rest is not necessary to include; it basically checks if the error was caused by a dangerous client request. By default, ASP.NET will not allow HTML/Script tags to avoid XSS attacks; however these errors tend to be annoying and can be easily caused by bots so they can be ignored.

Summary

This is a quick and simple way to log errors in ASP.NET, just remember that if something went wrong while writing the file (e.g. process in use) then another exception would be thrown and your site will crash. It might be good to add other special measures to make sure you have permission to write in that directory and the file is not in use (always close the reader/writer once finished, but the using statement does do that).

Now that you have the file you could easily read the file using the StreamWriter class and include it in your admin dashboard if you have one.