禁用异常跟踪

很多时候异常是不可预料的,在每个Action方法或Controller上应用Exception Filter是不现实的。而且如果异常出现在View中也无法应用Filter。如RangeError.cshtml这个View加入下面代码:

@model int

@{
var count = 0;
var number = Model / count;
} ...

运行程序后,将会显示如下信息:

MVC异常的统一处理-LMLPHP

显然程序发布后不应该显示这些信息给用户看。我们可以通过配置Web.config让应用程序不管在何时何地引发了异常都可以显示统一的友好错误信息。在Web.config文件中的<system.web>节点下添加如下子节点:

  <system.web>

    ...
<customErrors mode="On" defaultRedirect="/Content/RangeErrorPage.html"/>
</system.web>

这个配置只对远程访问有效,本地运行站点依然会显示跟踪信息。

使用内置的 Exceptin Filter

通过上面的演示,我们理解了Exceptin Filter在MVC背后是如何运行的。但我们并不会经常去创建自己的Exceptin Filter,因为微软在MVC框架中内置的 HandleErrorAttribute(实现了IExceptionFilter接口) 已经足够我们平时使用。它包含ExceptionType、View和Master三个属性。当ExceptionType属性指定类型的异常被引发时,这个Filter将用View属性指定的View(使用默认的Layout或Mast属性指定的Layout)来呈现一个页面。如下面代码所示:

...
[HandleError(ExceptionType = typeof(ArgumentOutOfRangeException), View = "RangeError")]
public string RangeTest(int id) {
if (id > 100) {
return String.Format("The id value is: {0}", id);
} else {
throw new ArgumentOutOfRangeException("id", id, "");
}
}
...

使用内置的HandleErrorAttribute,将异常信息呈现到View时,这个特性同时会传递一个HandleErrorInfo对象作为View的model。HandleErrorInfo类包含ActionName、ControllerName和Exception属性,如下面的 RangeError.cshtml 使用这个model来呈现信息:

@model HandleErrorInfo
@{
ViewBag.Title = "Sorry, there was a problem!";
} <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Range Error</title>
</head>
<body>
<h2>Sorry</h2>
<span>The value @(((ArgumentOutOfRangeException)Model.Exception).ActualValue)
was out of the expected range.</span>
<div>
@Html.ActionLink("Change value and try again", "Index")
</div>
<div style="display: none">
@Model.Exception.StackTrace
</div>
</body>
</html>
05-29 00:23