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 {
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; })()) { } }
source share