在ASP.NET MVC中,我们可以使用HandleErrorAttribute特性来具体指定如何处理Action抛出的异常.只要某个Action设置了HandleErrorAttribute特性,那么默认的,当这个Action抛出了异常时MVC将会显示Error视图,该视图位于~/Views/Shared目录下.
设置HandleError属性
可以通过设置下面这些属性来更改HandleErrorAttribute特性的默认处理:
- ExceptionType.指定过滤器处理那种或哪些类型的异常,如果没有指定该属性,过滤器将会处理所有的异常.
- View.指定发生异常时过滤器要显示的视图名称.
- Master.指定视图母版的名称,如果有的话.
- Order.指定过滤器应用的顺序,如果一个Action有多个HandleErrorAttribute过滤器.
指定Order属性
如果某个Action设置了多个HandleErrorAttribute,Order属性可以用来确定使用哪个过滤器.其值可以设置为从-1(最高优先级)到任何正整数之间的整数来标识其优先级,值越大,优先级别越低.Order属性遵循以下规则:
- 应用到Controller上的过滤器将会自动应用到该Controller的所有Action上.
- 如果Controller和Action都应用了HandleErrorAttribute,那么只要Order属性值相同,将会先执行Controller上的过滤器,而后才会执行Action上的过滤器.
- 对于相同Order属性的过滤器,其执行先后次序不定.
- 如果没有指定Order属性,则默认为-1,这意味着该过滤器将比其他的过滤器优先执行,除非其他过滤器指定了Order为-1.
- 如果有多个过滤器可适用,那么第一个可以处理该异常的过滤器会被首先调用,然后针对该异常的处理将会终结.
在View中获取异常信息
ASP.NET MVC框架将异常信息存储在ViewDataDictionary中来传递给Error视图,该ViewDataDictionary的Model属性即是ExceptionContext类的一个实例,这个ViewData有下面几个键:
ActionName:目标Action方法的名称
ControllerName:目标Controller的名称
Exception:异常对象.
启用自定义错误处理
下面我们来开启用于HandleErrorAttribute过滤器的自定义错误处理,打开程序的Web.config文件,在system.web节中加入一个customErrors元素,如下所示
<
system.web
>
<
customErrors
mode
="On"
defaultRedirect
="Error"
/>
</
system.web
>
处理Error视图中的错误
有时候在Error视图中也会发生错误,这时ASP.NET将会显示其默认的错误页面(黄底红字),为了避免这种情况的出现,我们在Web.config文件的customErrors节中来自定义错误页面,如下:
<
system.web
>
<
customErrors
mode
="On"
defaultRedirect
="GenericErrorPage.htm"
>
<
error
statusCode
="500"
redirect
="/Error.htm"
/>
</
customErrors
>
</
system.web
>
示例程序
下面的示例说明了如何对Controller和Action应用HandleErrorAttribute特性来自定义异常处理.
示例中HomeController有一个名为ThrowException的Action方法,在该Action中将会抛出一个ApplicationException类型的错误,这个Action应用了HandleErrorAttribute,但是没有设置任何参数.当该Action执行时将会抛出一个异常,显示默认的Error视图.
而ThrowNotImplemented方法则应用了设有两个参数的HandleErrorAttribute,View参数指定了自定义的Error视图名称:CustomErrorView,ExceptionType参数指定了该过滤器仅处理ThrowNotImplemented类型的异常.
Controller的HandleErrorAttribute则设置了Order参数为2,意味着该过滤器只会被在Index或About方法产生异常时执行.
同时示例给出了视图CustomErrorView和CustomError.Master的内容.
视图CustomErrorView显示异常的信息,比如抛出异常的Controller和Action的名称,异常的内容以及堆栈跟踪信息.
视图Index上有两个链接,分别指向了ThrowException和ThrowNotImplemented两个Action.
HomeController类
[HandleError(Order
=
2
)]
public
class
HomeController : Controller
{
public
ActionResult Index()
{
ViewData[
"
Message
"
]
=
"
Welcome to ASP.NET MVC!
"
;
return
View();
}
public
ActionResult About()
{
return
View();
}
[HandleError]
public
ActionResult ThrowException()
{
throw
new
ApplicationException();
}
[HandleError(View
=
"
CustomErrorView
"
, ExceptionType
=
typeof
(NotImplementedException))]
public
ActionResult ThrowNotImplemented()
{
throw
new
NotImplementedException();
}
}
视图 CustomErrorView
<
asp:Content
ID
="Content1"
ContentPlaceHolderID
="TitleContent"
runat
="server"
>
CustomErrorView
</
asp:Content
>
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
CustomErrorView
</
h2
>
<
p
>
Controller:
<%
=
((HandleErrorInfo)ViewData.Model).ControllerName
%>
</
p
>
<
p
>
Action:
<%
=
((HandleErrorInfo)ViewData.Model).ActionName
%>
</
p
>
<
p
>
Message:
<%
=
((HandleErrorInfo)ViewData.Model).Exception.Message
%>
</
p
>
<
p
>
Stack Trace:
<%
=
((HandleErrorInfo)ViewData.Model).Exception.StackTrace
%>
</
p
>
</
asp:Content
>
视图 Index
<
asp:Content
ID
="indexTitle"
ContentPlaceHolderID
="TitleContent"
runat
="server"
>
Home Page
</
asp:Content
>
<
asp:Content
ID
="indexContent"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
<%
=
Html.Encode(ViewData[
"
Message
"
])
%>
</
h2
>
<%
=
Html.ActionLink(
"
Throw An Exception
"
,
"
ThrowException
"
)
%>
(Default Error Page)
<
br
/><
br
/>
<%
=
Html.ActionLink(
"
Throw Not Implemented Exception
"
,
"
ThrowNotImplemented
"
)
%>
(Custom Error Page)
</
asp:Content
>
母版页
<%
@ Master Language
=
"
C#
"
Inherits
=
"
System.Web.Mvc.ViewMasterPage
"
%>
<!
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
<
html
xmlns
="http://www.w3.org/1999/xhtml"
>
<
head
runat
="server"
>
<
title
><
asp:ContentPlaceHolder
ID
="TitleContent"
runat
="server"
/></
title
>
<
link
href
="http://www.cnblogs.com/Content/Site.css"
rel
="stylesheet"
type
="text/css"
/>
<
style
type
="text/css"
>
body.error
{
background-color
:
Maroon
;
color
:
#696969
;
}
</
style
>
</
head
>
<
body
class
="error"
>
<
div
class
="page"
>
<
div
id
="header"
>
<
div
id
="title"
>
<
h1
>
A Custom Error Occurred
</
h1
>
</
div
>
<
div
id
="logindisplay"
>
<%
Html.RenderPartial(
"
LogOnUserControl
"
);
%>
</
div
>
<
div
id
="menucontainer"
>
<
ul
id
="menu"
>
<
li
>
<%
=
Html.ActionLink(
"
Home
"
,
"
Index
"
,
"
Home
"
)
%>
</
li
>
<
li
>
<%
=
Html.ActionLink(
"
About
"
,
"
About
"
,
"
Home
"
)
%>
</
li
>
</
ul
>
</
div
>
</
div
>
<
div
id
="main"
>
<
asp:ContentPlaceHolder
ID
="MainContent"
runat
="server"
/>
<
div
id
="footer"
>
</
div
>
</
div
>
</
div
>
</
body
>
</
html
>