2 // System.Web.HttpException
5 // Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (c) 2002 Patrik Torstensson
9 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Runtime.Serialization;
34 using System.Runtime.InteropServices;
35 using System.Security.Permissions;
37 using System.Web.Util;
38 using System.Web.Compilation;
43 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
44 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
48 public class HttpException : ExternalException
51 const string errorStyleFonts = "\"Verdana\",\"DejaVu Sans\",sans-serif";
53 public HttpException ()
57 public HttpException (string message)
62 public HttpException (string message, Exception innerException)
63 : base (message, innerException)
67 public HttpException (int httpCode, string message) : base (message)
73 protected HttpException (SerializationInfo info, StreamingContext context)
74 : base (info, context)
76 http_code = info.GetInt32 ("_httpCode");
79 [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
80 public override void GetObjectData (SerializationInfo info, StreamingContext context)
82 base.GetObjectData (info, context);
83 info.AddValue ("_httpCode", http_code);
87 public HttpException (int httpCode, string message, int hr)
93 public HttpException (string message, int hr)
98 public HttpException (int httpCode, string message, Exception innerException)
99 : base (message, innerException)
101 http_code = httpCode;
104 public string GetHtmlErrorMessage ()
107 if (HttpContext.Current.IsCustomErrorEnabled)
108 return GetCustomErrorDefaultMessage ();
110 if (!(this.InnerException is HtmlizedException))
111 return GetDefaultErrorMessage ();
113 return GetHtmlizedErrorMessage ();
115 // we need the try/catch block in case the
116 // problem was with MapPath, which will cause
117 // IsCustomErrorEnabled to throw an exception
118 return GetCustomErrorDefaultMessage ();
122 internal virtual string Description {
123 get { return "Error processing request."; }
126 void WriteFileTop (StringBuilder builder, string title)
128 builder.Append ("<?xml version=\"1.0\" ?>\n");
129 builder.Append ("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
130 builder.AppendFormat ("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title>{0}</title><style type=\"text/css\">", title);
131 builder.AppendFormat (
132 @"body {{font-family:{0};font-weight:normal;font-size: .7em;color:black;background-color: white}}
133 p {{font-family:{0};font-weight:normal;color:black;margin-top: -5px}}
134 b {{font-family:{0};font-weight:bold;color:black;margin-top: -5px}}
135 h1 {{ font-family:{0};font-weight:normal;font-size:18pt;color:red }}
136 h2 {{ font-family:{0};font-weight:normal;font-size:14pt;color:maroon }}
137 pre {{font-family:""Lucida Console"",""DejaVu Sans Mono"", monospace;font-size: 1.2em}}
138 div.bodyText {{font-family: {0}}}
139 table.sampleCode {{width: 100%; background-color: #ffffcc; }}
140 .errorText {{color: red; font-weight: bold}}
141 .marker {{font-weight: bold; color: black;text-decoration: none;}}
142 .version {{color: gray;}}
143 .error {{margin-bottom: 10px;}}
144 .expandable {{ text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }}", errorStyleFonts);
146 builder.AppendFormat (
147 "</style></head><body><h1>Server Error in '{0}' Application</h1><hr style=\"color: silver\"/>",
148 HtmlEncode (HttpRuntime.AppDomainAppVirtualPath));
151 void WriteFileBottom (StringBuilder builder, string trace1, string trace2)
154 builder.AppendFormat ("<![CDATA[\r\n{0}\r\n]]>\r\n", HttpUtility.HtmlEncode (trace1));
156 builder.AppendFormat ("<![CDATA[\r\n{0}\r\n]]>\r\n", HttpUtility.HtmlEncode (trace2));
157 builder.AppendFormat ("<hr style=\"color: silver\"/>{0}</body></html>\r\n", DateTime.UtcNow);
160 string GetCustomErrorDefaultMessage ()
162 StringBuilder builder = new StringBuilder ();
163 WriteFileTop (builder, "Runtime Error");
164 builder.Append (@"<p><strong>Description:</strong> An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.</p>
165 <p><strong>Details:</strong> To enable the details of this specific error message to be viewable on remote machines, please create a <customErrors> tag within a "web.config" configuration file located in the root directory of the current web application. This <customErrors> tag should then have its "mode" attribute set to "Off".</p>
166 <table class=""sampleCode""><tr><td><pre>
168 <!-- Web.Config Configuration File -->
170 <configuration>
173 <customErrors mode="Off"/>
175 </configuration></pre>
176 </td></tr></table><br/>
177 <p><strong>Notes:</strong> The current error page you are seeing can be replaced by a custom error page by modifying the "defaultRedirect" attribute of the application's <customErrors> configuration tag to point to a custom error page URL.</p>
178 <table class=""sampleCode""><tr><td><pre>
179 <!-- Web.Config Configuration File -->
181 <configuration>
183 <customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/>
186 </configuration></pre></td></tr></table>");
187 WriteFileBottom (builder, null, null);
188 return builder.ToString ();
191 string GetDefaultErrorMessage ()
193 Exception ex, baseEx;
194 ex = baseEx = GetBaseException ();
198 StringBuilder builder = new StringBuilder ();
199 WriteFileTop (builder, String.Format ("Error{0}", http_code != 0 ? " " + http_code : String.Empty));
200 builder.AppendFormat ("<h2><em>{0}</em></h2>\r\n", HtmlEncode (ex.Message));
201 builder.AppendFormat ("<p><strong>Description: </strong>{0}</p>\r\n", HtmlEncode (Description));
202 builder.Append ("<p><strong>Error Message: </strong>");
204 builder.AppendFormat ("HTTP {0}. ", http_code);
205 builder.AppendFormat ("{0}: {1}\r\n</p>\r\n", ex.GetType ().FullName, HtmlEncode (ex.Message));
207 if (baseEx != null) {
208 builder.AppendFormat ("<p><strong>Stack Trace: </strong></p>");
209 builder.Append ("<table summary=\"Stack Trace\" class=\"sampleCode\">\r\n<tr><td>");
210 WriteTextAsCode (builder, baseEx.ToString ());
211 builder.Append ("</td></tr>\r\n</table>\r\n");
213 WriteFileBottom (builder,
218 return builder.ToString ();
221 static string HtmlEncode (string s)
226 string res = HttpUtility.HtmlEncode (s);
227 return res.Replace ("\r\n", "<br />");
230 string GetHtmlizedErrorMessage ()
232 StringBuilder builder = new StringBuilder ();
233 HtmlizedException exc = (HtmlizedException) this.InnerException;
234 WriteFileTop (builder, exc.Title);
235 builder.AppendFormat ("<h2><em>{0}</em></h2>\r\n", exc.Title);
236 builder.AppendFormat ("<p><strong>Description: </strong>{0}\r\n</p>\r\n", HtmlEncode (exc.Description));
237 string errorMessage = HtmlEncode (exc.ErrorMessage).Replace ("\n", "<br/>");
238 builder.AppendFormat ("<p><strong>Error message: </strong></p><p>{0}</p>", errorMessage);
240 if (exc.FileName != null)
241 builder.AppendFormat ("<p><strong>File name: </strong> {0}</p>", HtmlEncode (exc.FileName));
243 if (exc.FileText != null) {
244 if (exc.SourceFile != exc.FileName)
245 builder.AppendFormat ("<p><strong>Source File: </strong>{0}</p>", exc.SourceFile);
247 if (exc is ParseException) {
248 builder.Append ("<p> <strong>Line: </strong>");
249 builder.Append (exc.ErrorLines [0]);
250 builder.Append ("</p>");
253 if (exc is ParseException) {
254 builder.Append ("<strong>Source Error: </strong>\r\n");
255 builder.Append ("<table summary=\"Source error\" class=\"sampleCode\">\r\n<tr><td>");
256 WriteSource (builder, exc);
257 builder.Append ("</td></tr>\r\n</table>\r\n");
259 builder.Append ("<table summary=\"Source file\" class=\"sampleCode\">\r\n<tr><td>");
260 WriteSource (builder, exc);
261 builder.Append ("</td></tr>\r\n</table>\r\n");
271 return builder.ToString ();
274 static void WriteTextAsCode (StringBuilder builder, string text)
276 builder.AppendFormat ("<pre>{0}</pre>", HtmlEncode (text));
280 static void WriteSource (StringBuilder builder, HtmlizedException e)
282 builder.Append ("<pre>");
283 WritePageSource (builder, e);
284 builder.Append ("</pre>\r\n");
288 static void WriteSource (StringBuilder builder, HtmlizedException e)
290 builder.Append ("<pre>");
291 if (e is CompilationException)
292 WriteCompilationSource (builder, e);
294 WritePageSource (builder, e);
296 builder.Append ("</pre>\r\n");
300 static void WriteCompilationSource (StringBuilder builder, HtmlizedException e)
302 int [] a = e.ErrorLines;
308 if (a != null && a.Length > 0)
311 TextReader reader = new StringReader (e.FileText);
312 while ((s = reader.ReadLine ()) != null) {
316 builder.Append ("<span style=\"color: red\">");
318 builder.AppendFormat ("Line {0}: {1}\r\n", line, HtmlEncode (s));
320 if (line == errline) {
321 builder.Append ("</span>");
322 errline = (++index < a.Length) ? a [index] : 0;
327 static void WritePageSource (StringBuilder builder, HtmlizedException e)
331 int beginerror = e.ErrorLines [0];
332 int enderror = e.ErrorLines [1];
333 int begin = beginerror - 3;
334 int end = enderror + 3;
338 TextReader reader = new StringReader (e.FileText);
339 while ((s = reader.ReadLine ()) != null) {
347 if (beginerror == line)
348 builder.Append ("<span style=\"color: red\">");
350 builder.AppendFormat ("{0}\r\n", HtmlEncode (s));
352 if (enderror <= line) {
353 builder.Append ("</span>");
354 enderror = end + 1; // one shot
359 public int GetHttpCode ()
364 public static HttpException CreateFromLastError (string message)
366 WebTrace.WriteLine ("CreateFromLastError");
367 return new HttpException (message, 0);