PageRenderTime 51ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Trunk/Elmah/src/Elmah/ErrorMailHtmlFormatter.cs

#
C# | 382 lines | 188 code | 77 blank | 117 comment | 14 complexity | b52ca2dea21d43593533b2b61a45a1a5 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #region License, Terms and Author(s)
  2. //
  3. // ELMAH - Error Logging Modules and Handlers for ASP.NET
  4. // Copyright (c) 2007 Atif Aziz. All rights reserved.
  5. //
  6. // Author(s):
  7. //
  8. // Atif Aziz, http://www.raboof.com
  9. //
  10. // This library is free software; you can redistribute it and/or modify it
  11. // under the terms of the New BSD License, a copy of which should have
  12. // been delivered along with this distribution.
  13. //
  14. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  16. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  17. // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  18. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  20. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. //
  26. #endregion
  27. [assembly: Elmah.Scc("$Id: ErrorMailHtmlFormatter.cs 25 2007-05-04 23:24:03Z azizatif $")]
  28. namespace Elmah
  29. {
  30. #region Imports
  31. using System;
  32. using TextWriter = System.IO.TextWriter;
  33. using HttpUtility = System.Web.HttpUtility;
  34. using NameValueCollection = System.Collections.Specialized.NameValueCollection;
  35. using HtmlTextWriter = System.Web.UI.HtmlTextWriter;
  36. using Html32TextWriter = System.Web.UI.Html32TextWriter;
  37. using HtmlTextWriterTag = System.Web.UI.HtmlTextWriterTag;
  38. using HtmlTextWriterAttribute = System.Web.UI.HtmlTextWriterAttribute;
  39. #endregion
  40. /// <summary>
  41. /// Formats the HTML to display the details of a given error that is
  42. /// suitable for sending as the body of an e-mail message.
  43. /// </summary>
  44. public class ErrorMailHtmlFormatter : ErrorTextFormatter
  45. {
  46. private HtmlTextWriter _writer;
  47. private Error _error;
  48. /// <summary>
  49. /// Returns the text/html MIME type that is the format provided
  50. /// by this <see cref="ErrorTextFormatter"/> implementation.
  51. /// </summary>
  52. public override string MimeType
  53. {
  54. get { return "text/html"; }
  55. }
  56. /// <summary>
  57. /// Formats a complete HTML document describing the given
  58. /// <see cref="Error"/> instance.
  59. /// </summary>
  60. public override void Format(TextWriter writer, Error error)
  61. {
  62. if (writer == null)
  63. throw new ArgumentNullException("writer");
  64. if (error == null)
  65. throw new ArgumentNullException("error");
  66. //
  67. // Create a HTML writer on top of the given writer and
  68. // write out the document. Note that the incoming
  69. // writer and error parameters are promoted to members
  70. // during formatting in order to avoid passing them
  71. // as context to each downstream method responsible
  72. // for rendering a part of the document. The important
  73. // assumption here is that Format will never be called
  74. // from more than one thread at the same time.
  75. //
  76. Html32TextWriter htmlWriter = new Html32TextWriter(writer);
  77. htmlWriter.RenderBeginTag(HtmlTextWriterTag.Html);
  78. _writer = htmlWriter;
  79. _error = error;
  80. try
  81. {
  82. RenderHead();
  83. RenderBody();
  84. }
  85. finally
  86. {
  87. _writer = null;
  88. _error = null;
  89. }
  90. htmlWriter.RenderEndTag(); // </html>
  91. htmlWriter.WriteLine();
  92. }
  93. /// <summary>
  94. /// Gets the <see cref="HtmlTextWriter"/> used for HTML formatting.
  95. /// </summary>
  96. /// <remarks>
  97. /// This property is only available to downstream methods in the
  98. /// context of the <see cref="Format"/> method call.
  99. /// </remarks>
  100. protected HtmlTextWriter Writer
  101. {
  102. get { return _writer; }
  103. }
  104. /// <summary>
  105. /// Gets the <see cref="Error"/> object for which a HTML document
  106. /// is being formatted.
  107. /// </summary>
  108. /// <remarks>
  109. /// This property is only available to downstream methods in the
  110. /// context of the <see cref="Format"/> method call.
  111. /// </remarks>
  112. protected Error Error
  113. {
  114. get { return _error; }
  115. }
  116. /// <summary>
  117. /// Renders the &lt;head&gt; section of the HTML document.
  118. /// </summary>
  119. protected virtual void RenderHead()
  120. {
  121. HtmlTextWriter writer = this.Writer;
  122. writer.RenderBeginTag(HtmlTextWriterTag.Head);
  123. //
  124. // Write the document title and style.
  125. //
  126. writer.RenderBeginTag(HtmlTextWriterTag.Title);
  127. writer.Write("Error: ");
  128. HttpUtility.HtmlEncode(this.Error.Message, writer);
  129. writer.RenderEndTag(); // </title>
  130. writer.WriteLine();
  131. RenderStyle();
  132. writer.RenderEndTag(); // </head>
  133. writer.WriteLine();
  134. }
  135. /// <summary>
  136. /// Renders the &lt;body&gt; section of the HTML document.
  137. /// </summary>
  138. protected virtual void RenderBody()
  139. {
  140. HtmlTextWriter writer = this.Writer;
  141. writer.RenderBeginTag(HtmlTextWriterTag.Body);
  142. RenderSummary();
  143. if (this.Error.Detail.Length != 0)
  144. {
  145. RenderDetail();
  146. }
  147. RenderCollections();
  148. RenderFooter();
  149. writer.RenderEndTag(); // </body>
  150. writer.WriteLine();
  151. }
  152. /// <summary>
  153. /// Renders the footer content that appears at the end of the
  154. /// HTML document body.
  155. /// </summary>
  156. protected virtual void RenderFooter()
  157. {
  158. HtmlTextWriter writer = this.Writer;
  159. writer.RenderBeginTag(HtmlTextWriterTag.P);
  160. PoweredBy poweredBy = new PoweredBy();
  161. poweredBy.RenderControl(writer);
  162. writer.RenderEndTag();
  163. }
  164. /// <summary>
  165. /// Renders the &lt;style&gt; element along with in-line styles
  166. /// used to format the body of the HTML document.
  167. /// </summary>
  168. protected virtual void RenderStyle()
  169. {
  170. HtmlTextWriter writer = this.Writer;
  171. writer.RenderBeginTag(HtmlTextWriterTag.Style);
  172. writer.WriteLine(@"
  173. body { font-family: verdana, arial, helvetic; font-size: x-small; }
  174. td, th, pre { font-size: x-small; }
  175. #errorDetail { padding: 1em; background-color: #FFFFCC; }
  176. #errorMessage { font-size: medium; font-style: italic; color: maroon; }
  177. h1 { font-size: small; }");
  178. writer.RenderEndTag(); // </style>
  179. writer.WriteLine();
  180. }
  181. /// <summary>
  182. /// Renders the details about the <see cref="Error" /> object in
  183. /// body of the HTML document.
  184. /// </summary>
  185. protected virtual void RenderDetail()
  186. {
  187. HtmlTextWriter writer = this.Writer;
  188. //
  189. // Write the full text of the error.
  190. //
  191. writer.AddAttribute(HtmlTextWriterAttribute.Id, "errorDetail");
  192. writer.RenderBeginTag(HtmlTextWriterTag.Pre);
  193. writer.InnerWriter.Flush();
  194. HttpUtility.HtmlEncode(this.Error.Detail, writer.InnerWriter);
  195. writer.RenderEndTag(); // </pre>
  196. writer.WriteLine();
  197. }
  198. /// <summary>
  199. /// Renders a summary about the <see cref="Error"/> object in
  200. /// body of the HTML document.
  201. /// </summary>
  202. protected virtual void RenderSummary()
  203. {
  204. HtmlTextWriter writer = this.Writer;
  205. Error error = this.Error;
  206. //
  207. // Write the error type and message.
  208. //
  209. writer.AddAttribute(HtmlTextWriterAttribute.Id, "errorMessage");
  210. writer.RenderBeginTag(HtmlTextWriterTag.P);
  211. HttpUtility.HtmlEncode(error.Type, writer);
  212. writer.Write(": ");
  213. HttpUtility.HtmlEncode(error.Message, writer);
  214. writer.RenderEndTag(); // </p>
  215. writer.WriteLine();
  216. //
  217. // Write out the time, in UTC, at which the error was generated.
  218. //
  219. if (error.Time != DateTime.MinValue)
  220. {
  221. writer.RenderBeginTag(HtmlTextWriterTag.P);
  222. writer.Write("Generated: ");
  223. HttpUtility.HtmlEncode(error.Time.ToString("r"), writer);
  224. writer.RenderEndTag(); // </p>
  225. writer.WriteLine();
  226. }
  227. }
  228. /// <summary>
  229. /// Renders the diagnostic collections of the <see cref="Error" /> object in
  230. /// body of the HTML document.
  231. /// </summary>
  232. protected virtual void RenderCollections()
  233. {
  234. RenderCollection(this.Error.ServerVariables, "Server Variables");
  235. }
  236. /// <summary>
  237. /// Renders a collection as a table in HTML document body.
  238. /// </summary>
  239. /// <remarks>
  240. /// This method is called by <see cref="RenderCollections"/> to
  241. /// format a diagnostic collection from <see cref="Error"/> object.
  242. /// </remarks>
  243. protected virtual void RenderCollection(NameValueCollection collection, string caption)
  244. {
  245. if (collection == null || collection.Count == 0)
  246. {
  247. return;
  248. }
  249. HtmlTextWriter writer = this.Writer;
  250. writer.RenderBeginTag(HtmlTextWriterTag.H1);
  251. HttpUtility.HtmlEncode(caption, writer);
  252. writer.RenderEndTag(); // </h1>
  253. writer.WriteLine();
  254. //
  255. // Write a table with each key in the left column
  256. // and its value in the right column.
  257. //
  258. writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "5");
  259. writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
  260. writer.AddAttribute(HtmlTextWriterAttribute.Border, "1");
  261. writer.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
  262. writer.RenderBeginTag(HtmlTextWriterTag.Table);
  263. //
  264. // Write the column headings.
  265. //
  266. writer.AddAttribute(HtmlTextWriterAttribute.Valign, "top");
  267. writer.RenderBeginTag(HtmlTextWriterTag.Tr);
  268. writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
  269. writer.RenderBeginTag(HtmlTextWriterTag.Th);
  270. writer.Write("Name");
  271. writer.RenderEndTag(); // </th>
  272. writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
  273. writer.RenderBeginTag(HtmlTextWriterTag.Th);
  274. writer.Write("Value");
  275. writer.RenderEndTag(); // </th>
  276. writer.RenderEndTag(); // </tr>
  277. //
  278. // Write the main body of the table containing keys
  279. // and values in a two-column layout.
  280. //
  281. foreach (string key in collection.Keys)
  282. {
  283. writer.AddAttribute(HtmlTextWriterAttribute.Valign, "top");
  284. writer.RenderBeginTag(HtmlTextWriterTag.Tr);
  285. writer.RenderBeginTag(HtmlTextWriterTag.Td);
  286. HttpUtility.HtmlEncode(key, writer);
  287. writer.RenderEndTag(); // </td>
  288. writer.RenderBeginTag(HtmlTextWriterTag.Td);
  289. string value = Mask.NullString(collection[key]);
  290. if (value.Length != 0)
  291. {
  292. HttpUtility.HtmlEncode(value, writer);
  293. }
  294. else
  295. {
  296. writer.Write("&nbsp;");
  297. }
  298. writer.RenderEndTag(); // </td>
  299. writer.RenderEndTag(); // </tr>
  300. }
  301. writer.RenderEndTag(); // </table>
  302. writer.WriteLine();
  303. }
  304. }
  305. }