HTML exception formatting for sending SysAdmin email in C #

Our error handler sends SysAdmin exception messages. Now they look bad like plain text.

Is there a way to take an exception and format it in beautiful html so that SysAdmin can read it more easily?

+4
source share
3 answers
<pre> ... htmlencoded output from Exception.ToString() goes here ... </pre> 
+8
source

I would serialize the exception into an XML element and then I format it using special XSLT.

There is an interesting approach to serializing Exception , which you can read here: Serializing Exceptions for XML . To summarize it, if you try to decorate your own class that inherits from System.Exception with the [Serializable] attribute, and then use the XmlSerializer class on it, you will get a runtime exception due to the Exception.Data property that implements System.Collections.IDictionary . This way you can easily use the new System.Xml.Linq API (new as .NET 3.5).

Here is a simple program that throws an exception and formats it as HTML.

 using System; using System.IO; using System.Text; using System.Xml; using System.Xml.Xsl; using ConsoleApplication2.Properties; class Program { public static void Main(string[] args) { try { //throw an DivideByZeroException var a=0; var b=1/a; } catch (Exception ex) { //using the ExceptionXElement class var xmlException = new ExceptionXElement(ex); XslCompiledTransform myXslTrans = new XslCompiledTransform(); //Resources.formatter is the xsl file added as a Resource to the project (ConsoleApplication2.Properties.Resources.formatter) //So, here we load the xsl myXslTrans.Load(XmlReader.Create(new StringReader(Resources.formatter))); //initialize a TextWriter, in this case a StringWriter and set it to write to a StringBuilder StringBuilder stringBuilder = new StringBuilder(); XmlTextWriter myWriter = new XmlTextWriter(new StringWriter(stringBuilder)); //apply the XSL transformations to the xmlException and output them to the XmlWriter myXslTrans.Transform(xmlException.CreateReader(), null, myWriter); //outputting to the console the HTML exception (you can send it as the message body of an email) Console.WriteLine(stringBuilder); } } } 

Here is Formatter.xsl

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="utf-8" indent="no"/> <xsl:template match="/"> <html> <body> <h1> <xsl:value-of select="name(/*)"/> </h1> <h2> <xsl:value-of select="//Message"/> </h2> <table border="1"> <tr bgcolor="#9acd32"> <th>StackTrace</th> </tr> <xsl:for-each select="//Frame"> <tr> <td> <xsl:value-of select="."/> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet> 

And here is the definition of the ExceptionXElement class :

 using System; using System.Collections; using System.Linq; using System.Xml.Linq; /// <summary>Represent an Exception as XML data.</summary> public class ExceptionXElement : XElement { /// <summary>Create an instance of ExceptionXElement.</summary> /// <param name="exception">The Exception to serialize.</param> public ExceptionXElement(Exception exception) : this(exception, false) { } /// <summary>Create an instance of ExceptionXElement.</summary> /// <param name="exception">The Exception to serialize.</param> /// <param name="omitStackTrace"> /// Whether or not to serialize the Exception.StackTrace member /// if it not null. /// </param> public ExceptionXElement(Exception exception, bool omitStackTrace) : base(new Func<XElement>(() => { // Validate arguments if (exception == null) { throw new ArgumentNullException("exception"); } // The root element is the Exception type XElement root = new XElement (exception.GetType().ToString()); if (exception.Message != null) { root.Add(new XElement("Message", exception.Message)); } // StackTrace can be null, eg: // new ExceptionAsXml(new Exception()) if (!omitStackTrace && exception.StackTrace != null) { root.Add ( new XElement("StackTrace", from frame in exception.StackTrace.Split('\n') let prettierFrame = frame.Substring(6).Trim() select new XElement("Frame", prettierFrame)) ); } // Data is never null; it empty if there is no data if (exception.Data.Count > 0) { root.Add ( new XElement("Data", from entry in exception.Data.Cast<DictionaryEntry>() let key = entry.Key.ToString() let value = (entry.Value == null) ? "null" : entry.Value.ToString() select new XElement(key, value)) ); } // Add the InnerException if it exists if (exception.InnerException != null) { root.Add ( new ExceptionXElement (exception.InnerException, omitStackTrace) ); } return root; })()) { } } 
+2
source

I was thinking about something in more detail about creating an html file with the tag% message%. Put the html file in your resources so you can name it as a string. Then just use string.Replace ("% message%", error.Message); then write about it. I read a good solution somewhere. I will find an article and edit my answer

I changed the part of my code that does something similar. See if it helps

 public System.Net.Mail.AlternateView GenerateHTMLErrorEmail(Exception ex) { string body = ProductionEmailer.Properties.Resources.ShippedEmail; //Build replacement collection to replace fields in email.html file body = body.Replace("%MESSAGE%", ex.Message); AlternateView html = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html); //add a image to the html email, optional Bitmap b = new Bitmap(Properties.Resources.html_email_header_01); ImageConverter ic = new ImageConverter(); Byte[] ba = (Byte[])ic.ConvertTo(b, typeof(Byte[])); MemoryStream logo = new MemoryStream(ba); LinkedResource header1 = new LinkedResource(logo, "image/gif"); header1.ContentId = "header1"; html.LinkedResources.Add(header1); return html; } 
+1
source

All Articles