一、应用场景

 对于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-异常处理&自定义错误页的更多相关文章

  1. ASP.NET MVC下自定义错误页和展示错误页的几种方式

    在网站运行中,错误是不可避免的,错误页的产生也是不可缺少的. 这几天看了博友的很多文章,自己想总结下我从中学到的和实际中配置的. 首先,需要知道产生错误页的来源,一种是我们的.NET平台抛出的,一种是 ...

  2. 在Asp.Net的Global.asax中Application_Error跳转到自定义错误页无效的解决办法

    在开发Asp.Net系统的时候,我们很多时候希望系统发生错误后能够跳转到一个自定义的错误页面,于是我们经常会在Global.asax中的Application_Error方法中使用Response.R ...

  3. 解决 ASP.NET Core 自定义错误页面对 Middleware 异常无效的问题

    我们基于 Razor Class Library 实现了自定义错误页面的公用类库(详见之前的随笔),但是在实际使用时发现如果在 middleware 中发生了异常,则不能显示自定义错误页面,而是返回默 ...

  4. MVC自定义错误页404静态页

    昨天公司要求给所有项目添加自定义404错误页,具体的要求实现的有以下几点: 1.实现自定义错误(如各种error,404等)跳转到指定的页面 2.所指定的页面输出的http状态值必须是404或其他指定 ...

  5. 关于在 ASP.NET 的 Global.asax 中 Application_Error 方法内,设置跳转到自定义错误页无效的问题

    转自:https://www.cnblogs.com/OpenCoder/p/5070645.html 在 Global.asax 中的 Application_Error 方法中,使用 Respon ...

  6. ASP.NET MVC异常处理

    ASP.NET MVC异常处理方案 如何保留异常前填写表单的数据 ASP.NET MVC中的统一化自定义异常处理 MVC过滤器详解 MVC过滤器使用案例:统一处理异常顺道精简代码 ASP.NET MV ...

  7. ASP.NET MVC中的错误处理

    ASP.NET MVC中的错误的错误处理跨越了两个主要领域:程序异常和路由异常的处理.前者是关于在控制器和视图中捕获错误的;而后者更多是有关重定向和HTTP错误的. 1.在WebConfig中把过滤器 ...

  8. 转:【译】Asp.net MVC 利用自定义RouteHandler来防止图片盗链

    [译]Asp.net MVC 利用自定义RouteHandler来防止图片盗链   你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你 ...

  9. 【转】Asp.net MVC 通过自定义ControllerFactory实现构造器注入(重写DefaultControllerFactory)

    [转]Asp.net MVC 通过自定义ControllerFactory实现构造器注入 一.重写ControllerFactory的GetControllerInstance ControllerF ...

随机推荐

  1. Dynamics 365 for CRM:CRM与ADFS安装到同一台服务器,需修改ADFS服务端口号

    CRM与ADFS安装到同一台服务器时,出现PluginRegistrationTool 及 CRM Outlook Client连接不上,需要修改ADFS的服务端口号,由默认的808修改为809: P ...

  2. Chrome浏览器及调试教程

    ==>(微信公众号:IT知更鸟)欢迎关注<^>@<^> Chrome浏览器及调试教程 在web开发过程中,我们在写JavaScript脚本时难免会遇到各种bug,这时,我 ...

  3. 配置tomcat8数据源(采用局部数据源方式)

    tomcat提供两种数据源配置方式,全局和局部.全局的话对于所有web应用都生效,局部只对于配置的某一个web生效. 步骤: 1.将mysql的jdbc驱动复制到tomcat的lib路径下. 2.在t ...

  4. 福州大学W班-Beta冲刺评分

    作业链接 https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1715W/homework/1428 作业要求 1.博客具体要求 昨天的困 ...

  5. 201621123068 作业07-Java GUI编程

    1. 本周学习总结 1.1 思维导图:Java图形界面总结 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 注册.事件.事件源.监听 1.2 任意编写事件处理相 ...

  6. 201621123054 《Java程序设计》第六周实验总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 1.2 可选:使用常规方法总结其他上课内容. 2 ...

  7. python的Flask 介绍

    Flask 介绍 知识点 微框架.WSGI.模板引擎概念 使用 Flask 做 web 应用 模板的使用 根据 URL 返回特定网页 实验步骤 1. 什么是 Flask? Flask 是一个 web ...

  8. CentOS7安装配置iptables防火墙

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/50779761 CentOS7默认的防火墙不是iptables,而是firewall ...

  9. Java代码风格和在idea中的一些设置

    源文件基本设置 1. 文件名 驼峰标识,.java结尾 2. 编码 统一为UTF-8 Transport...可以解决property文件不能正常显示为中文的问题 3. 特殊字符 尽量使用转义字符(\ ...

  10. aix 6.1系统怎么安装?这里有详细图文教程

    今年六月,我们公司出现了一次非常严重的数据丢失的事故.生产服务器崩溃导致所有的业务都陷于停滞,而且由于涉及到公司机密又无法贸然到数据恢复公司进行恢复,可是自己又无法解决.权衡利弊还是决定找一家有保密资 ...