ASP.NET MVC-异常处理&自定义错误页
一、应用场景
对于B/S应用程序,在部署到正式环境运行的过程中,很有可能出现一些在前期测试过程中没有发现的一些异常或者错误,或者说只有在特定条件满足时才会发生的一些异常,对于使用ASP.NET MVC开发的应用程序站点,在部署到IIS上后,如果开发人员未对程序进行错误处理,那么一旦程序出现未处理的错误或异常,用户将看到一个让人感到及其困惑的错误堆栈跟踪页面,使得站点的用户体验下降,从程序的角度上来说,不做自定义错误处理也不利于程序出问题时的根源查找,因为很多时候有些错误只在特定条件下满足时才重现,一旦错过,可能就需要花大量时间去测试来重现问题,如果此时开发人员有对程序中的运行时异常进行日志记录,那么或许将提供一些有价值的错误根源信息,下面我将向下大家讲解如何实现自定义异常处理并跳转到友好的错误提示页面。
二、异常处理&自定义错误页
1、通过异常过滤器 实现异常处理和自定义错误页
asp.net mvc 提供了 异常过滤器 的方式来实现当执行controller中某个action方法时抛出了未处理的异常时的捕捉,mvc中的异常过滤器是以特性(Attribute)的形式存在的,定义一个自定义异常过滤器只需要两个步骤:
1、定义一个类,继承FilterAttribute类,并实现IExceptionFilter接口 2、应用自定义异常过滤器至指定的 action方法 或 controller类 或 全局应用。
异常过滤器代码
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace Blog20180413.Filters
{
public class CustomExceptionFilterAttribute : FilterAttribute, IExceptionFilter
{
//log4net组件,用于日志记录。
static readonly ILog log = LogManager.GetLogger(typeof(CustomExceptionFilterAttribute));
public void OnException(ExceptionContext filterContext)
{
//对捕获到的异常信息进行日志记录,方便开发人员排查问题。
log.Error("应用程序异常", filterContext.Exception); //跳转到自定义的错误页,增强用户体验。
ActionResult result = new ViewResult() { ViewName = "CustomErrorPage" };
filterContext.Result = result;
//异常处理结束后,一定要将ExceptionHandled设置为true,否则仍然会继续抛出错误。
filterContext.ExceptionHandled = true;
}
}
}
使用异常过滤器
using Blog20180413.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace Blog20180413.Controllers
{
public class TestExceptionHandleController : Controller
{
[CustomExceptionFilter]
public ActionResult Index()
{
string str = string.Empty;
//将抛出转换异常
int result = int.Parse(str);
return View();
}
}
}
注意:
第二个步骤中提到,可以将自定义异常过滤器 只应用到 action或者controller,如果只想将指定的异常过滤器以特性的形式应用到指定的一个或者多个controller或者action,而不想应用到所有的controller或者action,那么必须将该异常过滤器继承FilterAttribute类,这是因为mvc框架是通过FilterAttributeFilterProvider.GetFilters来获取标记在指定controller或者action上的异常过滤器特性的,而GetFilters内部逻辑要求必须继承自FilterAttribute类。
如果需要将自定义的异常过滤器应用到所有的controller的action上,那么需要将该自定义异常过滤器注册到全局,代码如下:
using Blog20180413.Filters;
using System.Web;
using System.Web.Mvc; namespace Blog20180413
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomExceptionFilterAttribute());
}
}
}
2、通过在Global.asax 中定义Application_Error方法 实现异常处理和自定义错误页
上面提到的 自定义异常过滤器只能捕获在执行action方法过程中抛出的异常(即使注册为全局过滤器也只能捕获action方法执行过程中抛出的异常),如果需要捕获更高级别的异常,也就是在请求执行过程中出现的任何异常(如在控制器的构造函数中抛出异常),那么可以使用该种方式,代码如下:
using log4net;
using log4net.Config;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace Blog20180413
{
public class MvcApplication : System.Web.HttpApplication
{
static readonly ILog log = LogManager.GetLogger(typeof(MvcApplication));
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
XmlConfigurator.ConfigureAndWatch(new FileInfo(Server.MapPath("~/web.config")));
} protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
//Server.ClearError();
//这里记录错误日志信息
log.Error("MvcApplication 捕获异常", exception);
//跳转到指定的自定义错误页
Response.Redirect("/CustomErrorHandle/CustomErrorPage");
}
}
}
3、通过配置system.web->customErrors节点 实现自定义错误页
当你的站点发生异常时,如果你只是想简单的跳转到一个自定义错误页面,而不是对异常进一步处理时,那么你可以简单的作如下配置操作即可:
需要在web.config中做如下配置:
<system.web>
<customErrors mode="On" defaultRedirect="CustomErrorPage">
</customErrors>
</system.web>
注意:这里的CustomErrorPage是一个视图文件,放在Shared共享目录下。
如果你注册了HandleErrorAttribute异常过滤器到全局,那么在你的错误页中将能获取到和异常相关的一些信息。但此时配置到defaultRedirect的值的必须是Error
也就是自定义错误视图页面的名称必须为Error.cshtml,并且放在Shared目录,当然,你也可以通过在创建HandleErrorAttribute全局过滤器的过程中,设置器View属性,这样你就可以不用讲错误视图的名称设置为Error了.如下:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
HandleErrorAttribute errorAttribute = new HandleErrorAttribute();
errorAttribute.View = "CustomErrorPage";
filters.Add(errorAttribute);
}
注册HandleErrorAttribute(使用默认的错误视图页面文件名)
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
定义Error.cshtml视图页
@{
Layout = null;
}
@model HandleErrorInfo
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Error</title>
</head>
<body>
<div>
@*通过HandleErrorAttribute异常过滤器捕获到的异常信息存储在Model属性中*@
@Model.Exception.Message
</div>
</body>
</html>
之所以通过注册HandleErrorAttribute过滤器捕获的异常在错误页中能获取异常信息可以看HandleErrorAttribute类的内部实现,发现加载错误视图页面的过程中,传递了一个HandleErrorInfo对象过去。
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
{
Exception innerException = filterContext.Exception;
if ((new HttpException(null, innerException).GetHttpCode() == ) && this.ExceptionType.IsInstanceOfType(innerException))
{
string controllerName = (string) filterContext.RouteData.Values["controller"];
string actionName = (string) filterContext.RouteData.Values["action"];
HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
ViewResult result = new ViewResult {
ViewName = this.View,
MasterName = this.Master,
ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
TempData = filterContext.Controller.TempData
};
filterContext.Result = result;
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = ;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
}
public string View
{
get
{
if (string.IsNullOrEmpty(this._view))
{
return "Error";
}
return this._view;
}
set =>
(this._view = value);
}
三、总结
总的来说,Application_Error方法用于处理针对请求管道级别的发生的异常错误,而Mvc异常过滤器则只能处理在执行action方法过程中出现的异常.能处理的范围相对Application_Error较小,但在实际项目开发中,用Mvc异常过滤器处理异常相对会多一点,因为我们的功能业务往往体现在控制器的action方法执行的过程中,也就是在这个过程中较容易产生异常。故开发中用Mvc异常过滤器就能适应大部分的异常处理需求。
ASP.NET MVC-异常处理&自定义错误页的更多相关文章
- ASP.NET MVC下自定义错误页和展示错误页的几种方式
在网站运行中,错误是不可避免的,错误页的产生也是不可缺少的. 这几天看了博友的很多文章,自己想总结下我从中学到的和实际中配置的. 首先,需要知道产生错误页的来源,一种是我们的.NET平台抛出的,一种是 ...
- 在Asp.Net的Global.asax中Application_Error跳转到自定义错误页无效的解决办法
在开发Asp.Net系统的时候,我们很多时候希望系统发生错误后能够跳转到一个自定义的错误页面,于是我们经常会在Global.asax中的Application_Error方法中使用Response.R ...
- 解决 ASP.NET Core 自定义错误页面对 Middleware 异常无效的问题
我们基于 Razor Class Library 实现了自定义错误页面的公用类库(详见之前的随笔),但是在实际使用时发现如果在 middleware 中发生了异常,则不能显示自定义错误页面,而是返回默 ...
- MVC自定义错误页404静态页
昨天公司要求给所有项目添加自定义404错误页,具体的要求实现的有以下几点: 1.实现自定义错误(如各种error,404等)跳转到指定的页面 2.所指定的页面输出的http状态值必须是404或其他指定 ...
- 关于在 ASP.NET 的 Global.asax 中 Application_Error 方法内,设置跳转到自定义错误页无效的问题
转自:https://www.cnblogs.com/OpenCoder/p/5070645.html 在 Global.asax 中的 Application_Error 方法中,使用 Respon ...
- ASP.NET MVC异常处理
ASP.NET MVC异常处理方案 如何保留异常前填写表单的数据 ASP.NET MVC中的统一化自定义异常处理 MVC过滤器详解 MVC过滤器使用案例:统一处理异常顺道精简代码 ASP.NET MV ...
- ASP.NET MVC中的错误处理
ASP.NET MVC中的错误的错误处理跨越了两个主要领域:程序异常和路由异常的处理.前者是关于在控制器和视图中捕获错误的;而后者更多是有关重定向和HTTP错误的. 1.在WebConfig中把过滤器 ...
- 转:【译】Asp.net MVC 利用自定义RouteHandler来防止图片盗链
[译]Asp.net MVC 利用自定义RouteHandler来防止图片盗链 你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你 ...
- 【转】Asp.net MVC 通过自定义ControllerFactory实现构造器注入(重写DefaultControllerFactory)
[转]Asp.net MVC 通过自定义ControllerFactory实现构造器注入 一.重写ControllerFactory的GetControllerInstance ControllerF ...
随机推荐
- java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用
先来讲解一下Semaphore信号灯的作用: 可以维护当前访问自身的线程个数,并提供了同步机制, 使用semaphore可以控制同时访问资源的线程个数 例如,实现一个文件允许的并发访问数. 请看下面 ...
- (译文)学习ES6非常棒的特性-深入研究var, let and const
Var var firstVar; //firstVar被声明,它的默认值是undefined var secondVar = 2; //secondVar被声明,被赋值2 先看一个例子: var i ...
- 云计算--网络原理与应用--20171123--网络地址转换NAT
NAT的概述 NAT的配置 实验 一. NAT的概述 NAT(Network address translation,网络地址转换)通过将内部网络的的私有地址翻译成全球唯一的共有网络IP地址,是内部网 ...
- 20162308 实验一《Java开发环境的熟悉》实验报告
a 20162308 实验一<Java开发环境的熟悉>实验报告 实验内容 使用JDK编译.运行简单的Java程序. 使用IDEA 编辑.编译.运行.调试Java程序. 实验要求 没有Lin ...
- Linux系统安装gcc/g++详细过程
下载: http://ftp.gnu.org/gnu/gcc/gcc-4.5.1/gcc-4.5.1.tar.bz2 浏览: http://ftp.gnu.org/gnu/gcc/gcc-4.5.1/ ...
- bzoj千题计划108:bzoj1018: [SHOI2008]堵塞的交通traffic
http://www.lydsy.com/JudgeOnline/problem.php?id=1018 关键点在于只有两行 所以一个2*m矩形连通情况只有6种 编号即对应代码中的a数组 线段树维护 ...
- python 面向对象之继承与派生
一:初识继承 1,什么是继承? 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题 继承是一种创建新类的方式,在python中,新建的类 ...
- C# 使用 GDI+ 给图片添加文字,并使文字自适应矩形区域
需求 需求是要做一个编辑文字的页面.用户在网页端写文字,文字区域是个矩形框,用户可以通过下方的拖动条调节文字大小. 如下图: 提交数据的时候前端传文字区域的左上角和右下角定位给后台.因为前端的字体大小 ...
- 常用cmd代码片段及.net core打包脚本分享
bat基础命令 注释:rem 注释~~ 输出:echo hello world 接收用户输入:%1 %2,第n个变量就用%n表示 当前脚本路径:%~dp0 当前目录路径:%cd% 设置变量:set c ...
- Python-函数-Day4
1.函数 1.1.集合 主要作用: 去重 关系测试, 交集\差集\并集\反向(对称)差集 a = {1,2,3,4} b ={3,4,5,6} a {1, 2, 3, 4} type(a) <c ...