PageRenderTime 67ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Elmah/Error.cs

https://bitbucket.org/AlfeG/elmah
C# | 423 lines | 208 code | 79 blank | 136 comment | 22 complexity | c1591357da971fdb50b725b492d3fa59 MD5 | raw file
Possible License(s): Apache-2.0
  1. #region License, Terms and Author(s)
  2. //
  3. // ELMAH - Error Logging Modules and Handlers for ASP.NET
  4. // Copyright (c) 2004-9 Atif Aziz. All rights reserved.
  5. //
  6. // Author(s):
  7. //
  8. // Atif Aziz, http://www.raboof.com
  9. //
  10. // Licensed under the Apache License, Version 2.0 (the "License");
  11. // you may not use this file except in compliance with the License.
  12. // You may obtain a copy of the License at
  13. //
  14. // http://www.apache.org/licenses/LICENSE-2.0
  15. //
  16. // Unless required by applicable law or agreed to in writing, software
  17. // distributed under the License is distributed on an "AS IS" BASIS,
  18. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. // See the License for the specific language governing permissions and
  20. // limitations under the License.
  21. //
  22. #endregion
  23. using System.Collections.Generic;
  24. [assembly: Elmah.Scc("$Id: Error.cs 824 2011-05-03 21:25:06Z azizatif $")]
  25. namespace Elmah
  26. {
  27. #region Imports
  28. using System;
  29. using System.Diagnostics;
  30. using System.Security;
  31. using System.Security.Principal;
  32. using System.Web;
  33. using System.Xml;
  34. using Thread = System.Threading.Thread;
  35. using NameValueCollection = System.Collections.Specialized.NameValueCollection;
  36. #endregion
  37. /// <summary>
  38. /// Represents a logical application error (as opposed to the actual
  39. /// exception it may be representing).
  40. /// </summary>
  41. public interface IExceptionWithData
  42. {
  43. NameValueCollection AdditionalData { get; }
  44. }
  45. [ Serializable ]
  46. public sealed class Error : ICloneable
  47. {
  48. private readonly Exception _exception;
  49. private string _applicationName;
  50. private string _hostName;
  51. private string _typeName;
  52. private string _source;
  53. private string _message;
  54. private string _detail;
  55. private string _user;
  56. private DateTime _time;
  57. private int _statusCode;
  58. private string _webHostHtmlMessage;
  59. private NameValueCollection _serverVariables;
  60. private NameValueCollection _queryString;
  61. private NameValueCollection _form;
  62. private NameValueCollection _cookies;
  63. private NameValueCollection _addData;
  64. /// <summary>
  65. /// Initializes a new instance of the <see cref="Error"/> class.
  66. /// </summary>
  67. public Error() {}
  68. /// <summary>
  69. /// Initializes a new instance of the <see cref="Error"/> class
  70. /// from a given <see cref="Exception"/> instance.
  71. /// </summary>
  72. public Error(Exception e) :
  73. this(e, null) {}
  74. /// <summary>
  75. /// Initializes a new instance of the <see cref="Error"/> class
  76. /// from a given <see cref="Exception"/> instance and
  77. /// <see cref="HttpContext"/> instance representing the HTTP
  78. /// context during the exception.
  79. /// </summary>
  80. public Error(Exception e, HttpContext context)
  81. {
  82. if (e == null)
  83. throw new ArgumentNullException("e");
  84. _exception = e;
  85. Exception baseException = e.GetBaseException();
  86. //
  87. // Load the basic information.
  88. //
  89. _hostName = Environment.TryGetMachineName(context);
  90. _typeName = baseException.GetType().FullName;
  91. _message = baseException.Message;
  92. _source = baseException.Source;
  93. _detail = e.ToString();
  94. _user = Mask.NullString(Thread.CurrentPrincipal.Identity.Name);
  95. _time = DateTime.Now;
  96. //
  97. // If this is an HTTP exception, then get the status code
  98. // and detailed HTML message provided by the host.
  99. //
  100. HttpException httpException = e as HttpException;
  101. if (httpException != null)
  102. {
  103. _statusCode = httpException.GetHttpCode();
  104. _webHostHtmlMessage = TryGetHtmlErrorMessage(httpException);
  105. }
  106. //
  107. // If the HTTP context is available, then capture the
  108. // collections that represent the state request as well as
  109. // the user.
  110. //
  111. if (context != null)
  112. {
  113. IPrincipal webUser = context.User;
  114. if (webUser != null
  115. && Mask.NullString(webUser.Identity.Name).Length > 0)
  116. {
  117. _user = webUser.Identity.Name;
  118. }
  119. HttpRequest request = context.Request;
  120. _serverVariables = CopyCollection(request.ServerVariables);
  121. _queryString = CopyCollection(request.QueryString);
  122. _form = CopyCollection(request.Form);
  123. _cookies = CopyCollection(request.Cookies);
  124. }
  125. if (e is IExceptionWithData)
  126. {
  127. IExceptionWithData exceptionWithData = e as IExceptionWithData;
  128. _addData = CopyCollection(exceptionWithData.AdditionalData);
  129. }
  130. }
  131. private static string TryGetHtmlErrorMessage(HttpException e)
  132. {
  133. Debug.Assert(e != null);
  134. try
  135. {
  136. return e.GetHtmlErrorMessage();
  137. }
  138. catch (SecurityException se)
  139. {
  140. // In partial trust environments, HttpException.GetHtmlErrorMessage()
  141. // has been known to throw:
  142. // System.Security.SecurityException: Request for the
  143. // permission of type 'System.Web.AspNetHostingPermission' failed.
  144. //
  145. // See issue #179 for more background:
  146. // http://code.google.com/p/elmah/issues/detail?id=179
  147. Trace.WriteLine(se);
  148. return null;
  149. }
  150. }
  151. /// <summary>
  152. /// Gets the <see cref="Exception"/> instance used to initialize this
  153. /// instance.
  154. /// </summary>
  155. /// <remarks>
  156. /// This is a run-time property only that is not written or read
  157. /// during XML serialization via <see cref="ErrorXml.Decode"/> and
  158. /// <see cref="ErrorXml.Encode(Error,XmlWriter)"/>.
  159. /// </remarks>
  160. public Exception Exception
  161. {
  162. get { return _exception; }
  163. }
  164. /// <summary>
  165. /// Gets or sets the name of application in which this error occurred.
  166. /// </summary>
  167. public string ApplicationName
  168. {
  169. get { return Mask.NullString(_applicationName); }
  170. set { _applicationName = value; }
  171. }
  172. /// <summary>
  173. /// Gets or sets name of host machine where this error occurred.
  174. /// </summary>
  175. public string HostName
  176. {
  177. get { return Mask.NullString(_hostName); }
  178. set { _hostName = value; }
  179. }
  180. /// <summary>
  181. /// Gets or sets the type, class or category of the error.
  182. /// </summary>
  183. public string Type
  184. {
  185. get { return Mask.NullString(_typeName); }
  186. set { _typeName = value; }
  187. }
  188. /// <summary>
  189. /// Gets or sets the source that is the cause of the error.
  190. /// </summary>
  191. public string Source
  192. {
  193. get { return Mask.NullString(_source); }
  194. set { _source = value; }
  195. }
  196. /// <summary>
  197. /// Gets or sets a brief text describing the error.
  198. /// </summary>
  199. public string Message
  200. {
  201. get { return Mask.NullString(_message); }
  202. set { _message = value; }
  203. }
  204. /// <summary>
  205. /// Gets or sets a detailed text describing the error, such as a
  206. /// stack trace.
  207. /// </summary>
  208. public string Detail
  209. {
  210. get { return Mask.NullString(_detail); }
  211. set { _detail = value; }
  212. }
  213. /// <summary>
  214. /// Gets or sets the user logged into the application at the time
  215. /// of the error.
  216. /// </summary>
  217. public string User
  218. {
  219. get { return Mask.NullString(_user); }
  220. set { _user = value; }
  221. }
  222. /// <summary>
  223. /// Gets or sets the date and time (in local time) at which the
  224. /// error occurred.
  225. /// </summary>
  226. public DateTime Time
  227. {
  228. get { return _time; }
  229. set { _time = value; }
  230. }
  231. /// <summary>
  232. /// Gets or sets the HTTP status code of the output returned to the
  233. /// client for the error.
  234. /// </summary>
  235. /// <remarks>
  236. /// For cases where this value cannot always be reliably determined,
  237. /// the value may be reported as zero.
  238. /// </remarks>
  239. public int StatusCode
  240. {
  241. get { return _statusCode; }
  242. set { _statusCode = value; }
  243. }
  244. /// <summary>
  245. /// Gets or sets the HTML message generated by the web host (ASP.NET)
  246. /// for the given error.
  247. /// </summary>
  248. public string WebHostHtmlMessage
  249. {
  250. get { return Mask.NullString(_webHostHtmlMessage); }
  251. set { _webHostHtmlMessage = value; }
  252. }
  253. /// <summary>
  254. /// Gets a collection representing the Web server variables
  255. /// captured as part of diagnostic data for the error.
  256. /// </summary>
  257. public NameValueCollection ServerVariables
  258. {
  259. get { return FaultIn(ref _serverVariables); }
  260. }
  261. /// <summary>
  262. /// Gets a collection representing the Web query string variables
  263. /// captured as part of diagnostic data for the error.
  264. /// </summary>
  265. public NameValueCollection QueryString
  266. {
  267. get { return FaultIn(ref _queryString); }
  268. }
  269. /// <summary>
  270. /// Gets a collection representing the form variables captured as
  271. /// part of diagnostic data for the error.
  272. /// </summary>
  273. public NameValueCollection Form
  274. {
  275. get { return FaultIn(ref _form); }
  276. }
  277. /// <summary>
  278. /// Gets a collection representing the client cookies
  279. /// captured as part of diagnostic data for the error.
  280. /// </summary>
  281. public NameValueCollection Cookies
  282. {
  283. get { return FaultIn(ref _cookies); }
  284. }
  285. public NameValueCollection AdditionalData
  286. {
  287. get { return FaultIn(ref _addData); }
  288. }
  289. /// <summary>
  290. /// Returns the value of the <see cref="Message"/> property.
  291. /// </summary>
  292. public override string ToString()
  293. {
  294. return this.Message;
  295. }
  296. /// <summary>
  297. /// Creates a new object that is a copy of the current instance.
  298. /// </summary>
  299. object ICloneable.Clone()
  300. {
  301. //
  302. // Make a base shallow copy of all the members.
  303. //
  304. Error copy = (Error) MemberwiseClone();
  305. //
  306. // Now make a deep copy of items that are mutable.
  307. //
  308. copy._serverVariables = CopyCollection(_serverVariables);
  309. copy._queryString = CopyCollection(_queryString);
  310. copy._form = CopyCollection(_form);
  311. copy._cookies = CopyCollection(_cookies);
  312. copy._addData = CopyCollection(_addData);
  313. return copy;
  314. }
  315. private static NameValueCollection CopyCollection(NameValueCollection collection)
  316. {
  317. if (collection == null || collection.Count == 0)
  318. return null;
  319. return new NameValueCollection(collection);
  320. }
  321. private static NameValueCollection CopyCollection(HttpCookieCollection cookies)
  322. {
  323. if (cookies == null || cookies.Count == 0)
  324. return null;
  325. NameValueCollection copy = new NameValueCollection(cookies.Count);
  326. for (int i = 0; i < cookies.Count; i++)
  327. {
  328. HttpCookie cookie = cookies[i];
  329. //
  330. // NOTE: We drop the Path and Domain properties of the
  331. // cookie for sake of simplicity.
  332. //
  333. copy.Add(cookie.Name, cookie.Value);
  334. }
  335. return copy;
  336. }
  337. private static NameValueCollection FaultIn(ref NameValueCollection collection)
  338. {
  339. if (collection == null)
  340. collection = new NameValueCollection();
  341. return collection;
  342. }
  343. }
  344. }