New test.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / HandleErrorAttribute.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Diagnostics.CodeAnalysis;\r
16     using System.Globalization;\r
17     using System.Web;\r
18     using System.Web.Mvc.Resources;\r
19 \r
20     [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",\r
21         Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]\r
22     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]\r
23     public class HandleErrorAttribute : FilterAttribute, IExceptionFilter {\r
24 \r
25         private const string _defaultView = "Error";\r
26 \r
27         private readonly object _typeId = new object();\r
28 \r
29         private Type _exceptionType = typeof(Exception);\r
30         private string _master;\r
31         private string _view;\r
32 \r
33         public Type ExceptionType {\r
34             get {\r
35                 return _exceptionType;\r
36             }\r
37             set {\r
38                 if (value == null) {\r
39                     throw new ArgumentNullException("value");\r
40                 }\r
41                 if (!typeof(Exception).IsAssignableFrom(value)) {\r
42                     throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture,\r
43                         MvcResources.ExceptionViewAttribute_NonExceptionType, value.FullName));\r
44                 }\r
45 \r
46                 _exceptionType = value;\r
47             }\r
48         }\r
49 \r
50         public string Master {\r
51             get {\r
52                 return _master ?? String.Empty;\r
53             }\r
54             set {\r
55                 _master = value;\r
56             }\r
57         }\r
58 \r
59         public override object TypeId {\r
60             get {\r
61                 return _typeId;\r
62             }\r
63         }\r
64 \r
65         public string View {\r
66             get {\r
67                 return (!String.IsNullOrEmpty(_view)) ? _view : _defaultView;\r
68             }\r
69             set {\r
70                 _view = value;\r
71             }\r
72         }\r
73 \r
74         public virtual void OnException(ExceptionContext filterContext) {\r
75             if (filterContext == null) {\r
76                 throw new ArgumentNullException("filterContext");\r
77             }\r
78             if (filterContext.IsChildAction) {\r
79                 return;\r
80             }\r
81 \r
82             // If custom errors are disabled, we need to let the normal ASP.NET exception handler\r
83             // execute so that the user can see useful debugging information.\r
84             if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) {\r
85                 return;\r
86             }\r
87 \r
88             Exception exception = filterContext.Exception;\r
89 \r
90             // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),\r
91             // ignore it.\r
92             if (new HttpException(null, exception).GetHttpCode() != 500) {\r
93                 return;\r
94             }\r
95 \r
96             if (!ExceptionType.IsInstanceOfType(exception)) {\r
97                 return;\r
98             }\r
99 \r
100             string controllerName = (string)filterContext.RouteData.Values["controller"];\r
101             string actionName = (string)filterContext.RouteData.Values["action"];\r
102             HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);\r
103             filterContext.Result = new ViewResult {\r
104                 ViewName = View,\r
105                 MasterName = Master,\r
106                 ViewData = new ViewDataDictionary<HandleErrorInfo>(model),\r
107                 TempData = filterContext.Controller.TempData\r
108             };\r
109             filterContext.ExceptionHandled = true;\r
110             filterContext.HttpContext.Response.Clear();\r
111             filterContext.HttpContext.Response.StatusCode = 500;\r
112 \r
113             // Certain versions of IIS will sometimes use their own error page when\r
114             // they detect a server error. Setting this property indicates that we\r
115             // want it to try to render ASP.NET MVC's error page instead.\r
116             filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;\r
117         }\r
118     }\r
119 }