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

在网站运行中,错误是不可避免的,错误页的产生也是不可缺少的。

这几天看了博友的很多文章,自己想总结下我从中学到的和实际中配置的。

首先,需要知道产生错误页的来源,一种是我们的.NET平台抛出的,一种是网站所依赖的宿主抛出的,一般来讲我们所依赖的宿主就是IIS了。

IIS中的错误页入口:

其中的错误码想必并不陌生

这里是在服务器上找不到所需资源时抛出的错误页,在这里可以设置需要展示的错误页面,只需将预定的错误页面加入服务器中,然后在指定状态码下配置路径即可。

这是请求在IIS中时,还未完全进入到asp.net mvc中,这里需要理解什么是未完全进入,IIS7+的版本中,不依赖于请求路径末尾的标识信息,利用mvc中的urlRoutingModule进行处理,在我们配置mvc的路由时,首先的第一条:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

便是隔离非mvc内部的使用文件,如果请求的只是服务器上的文件,那么路由便会在这里进行过滤,使之不匹配具体路由信息。

也就只是和mvc打了个招呼 然后就走了,没有进入mvc中搞事情。

第二种是,进入了asp.net mvc的管辖范围,然后在其中出错了,便是跳到我们在程序中配置的错误页了。

首先讲讲我从博友那里学到的、看到的几种方式。

第一种是在web.config中通过customError配置。

<customErrors mode="On" defaultRedirect="~/Error/ErrorPage">
     <error statusCode="404" redirect="~/Error/ErrorPage404" />
</customErrors>

但是这种方式不怎么令人接受,太过于简单,没有一点异常信息,并且有时候还不能起效果,我不太喜欢这种方式。

这种是用框架封装好的,利用的是将要说的第三种的强大方式实现的,当有异常发生又没得捕获时,最终利用的第三种方式自动实现。

第二种是利用HandlerErrorAttribute 特性,利用AOP的方式,当有异常出现时,便会进入具体实现了这个特性的,且被注册了的ExceptionAttribute职责中。

namespace SAssassin.Web.Core.Filter
{
    /// <summary>
    /// 异常处理之日志记载采用消息队列方式
    /// </summary>
    public class MyExceptionAttribute : HandleErrorAttribute
    {
        public static Queue<Exception> ExceptionQueue = new Queue<Exception>();
        public override void OnException(ExceptionContext filterContext)
        {
            ExceptionQueue.Enqueue(filterContext.Exception);
            filterContext.HttpContext.Response.Redirect("~/ErrorPage/CustomErrorPage");
            base.OnException(filterContext);
        }
    }
}

在这里,我可以得到异常信息,也可以解析具体的异常报错原因,比如404,500...  可以通过这种形势,将其转移到不同的自定义错误页面上,此处我增加了一个控制器

CustomErrorPageController,专门用来存放错误页面,原有的Shared下的Error.cshtml错误页面也仍然存在着。

我比较喜欢这种方式,一来可以看到异常信息,而来可以设计需要跳转的错误页面。

第三种方式也是最强大的、俗称"最后一道防线",从全局层面去捕捉异常的Application_Error

当网站初次启动时,会执行一个特殊的动作,Application_start 首先执行,也只初始化一次。这个也是Application 中的事件。

        //
        // 摘要:
        //     ASP.NET 将 HTTP 标头发送到客户端之前发生。
        public event EventHandler PreSendRequestHeaders;
        //
        // 摘要:
        //     在选择该处理程序对请求作出响应时发生。
        public event EventHandler MapRequestHandler;
        //
        // 摘要:
        //     释放应用程序时发生。
        public event EventHandler Disposed;
        //
        // 摘要:
        //     作为执行的 HTTP 管道链中的第一个事件发生,当 ASP.NET 的请求做出响应。
        public event EventHandler BeginRequest;
        //
        // 摘要:
        //     当安全模块已建立的用户标识时出现。
        public event EventHandler AuthenticateRequest;
        //
        // 摘要:
        //     当安全模块已建立的用户标识时出现。
        public event EventHandler PostAuthenticateRequest;
        //
        // 摘要:
        //     安全模块已验证用户身份验证时发生。
        public event EventHandler AuthorizeRequest;
        //
        // 摘要:
        //     当前请求的用户已被授权时发生。
        public event EventHandler PostAuthorizeRequest;
        //
        // 摘要:
        //     当 ASP.NET 完成授权事件以便从缓存中,跳过的事件处理程序 (例如,一个页面或 XML Web 服务) 执行的请求提供服务的缓存模块时发生。
        public event EventHandler ResolveRequestCache;
        //
        // 摘要:
        //     ASP.NET 将绕过当前事件处理程序的执行,并允许缓存模块以处理从缓存请求时发生。
        public event EventHandler PostResolveRequestCache;
        //
        // 摘要:
        //     ASP.NET 将内容发送到客户端之前发生。
        public event EventHandler PreSendRequestContent;
        //
        // 摘要:
        //     当 ASP.NET 已映射到相应的事件处理程序的当前请求时出现。
        public event EventHandler PostMapRequestHandler;
        //
        // 摘要:
        //     当 ASP.NET 已完成处理的事件处理程序时发生 System.Web.HttpApplication.LogRequest 事件。
        public event EventHandler PostLogRequest;
        //
        // 摘要:
        //     已释放与请求相关联的托管的对象时发生。
        public event EventHandler RequestCompleted;
        //
        // 摘要:
        //     获取与当前的请求相关联的请求状态 (例如,会话状态) 时发生。
        public event EventHandler PostAcquireRequestState;
        //
        // 摘要:
        //     ASP.NET 开始执行事件处理程序 (例如,一个页面或 XML Web 服务) 之前发生。
        public event EventHandler PreRequestHandlerExecute;
        //
        // 摘要:
        //     当 ASP.NET 事件处理程序 (例如,一个页面或 XML Web 服务) 完成执行时发生。
        public event EventHandler PostRequestHandlerExecute;
        //
        // 摘要:
        //     ASP.NET 完成执行所有请求事件处理程序后发生。 此事件会导致状态模块保存当前的状态数据。
        public event EventHandler ReleaseRequestState;
        //
        // 摘要:
        //     当 ASP.NET 已完成执行所有请求事件处理程序和存储数据的请求状态时发生。
        public event EventHandler PostReleaseRequestState;
        //
        // 摘要:
        //     当 ASP.NET 完成执行事件处理程序,以便让缓存模块存储将用于为从缓存中的后续请求提供服务的响应时发生。
        public event EventHandler UpdateRequestCache;
        //
        // 摘要:
        //     当 ASP.NET 完成更新的缓存模块和存储用于为从缓存中的后续请求提供服务的响应时发生。
        public event EventHandler PostUpdateRequestCache;
        //
        // 摘要:
        //     ASP.NET 执行当前请求的任何日志记录之前发生。
        public event EventHandler LogRequest;
        //
        // 摘要:
        //     当 ASP.NET 获取与当前的请求相关联的当前状态 (例如,会话状态)。
        public event EventHandler AcquireRequestState;
        //
        // 摘要:
        //     作为执行的 HTTP 管道链中的最后一个事件发生,当 ASP.NET 的请求做出响应。
        public event EventHandler EndRequest;
        //
        // 摘要:
        //     当引发未处理的异常时发生。
        public event EventHandler Error;

看到最后一个事件,当引发未处理的异常时发生,便是最后一道防线登场了。如果没有用aop的方式捕捉异常,那么就是Application _Error登场了。

在Global.asax中我们可以写上这个方法

        /// <summary>
        /// 可以完成全局异常处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_Error(object sender, EventArgs e)
        {
            // 在出现未处理的错误时运行的代码
            var error = Server.GetLastError();
            var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;

            //如果不是HttpException记录错误信息
            if (code != 404)
            {
                //此处邮件或日志记录错误信息
            }

            Response.Write("出错");
            Server.ClearError();

            string path = Request.Path;
            Context.RewritePath(string.Format("~/Errors/Http{0}", code), false);
            IHttpHandler httpHandler = new MvcHttpHandler();
            httpHandler.ProcessRequest(Context);
            Context.RewritePath(path, false);
        }

这个方法中,我们也可以得到异常信息,记录日志或是邮件通知,

同样可以根据错误码进行相应的跳转错误页面。

也可以在当前错误页面中添加额外的信息。

很是强大。

如果没有写这个方法,则利用框架封装的默认方法。当在web.config中配置了customError节点时,便是这个方法来帮忙处理。

或许还有更多更好的方式。望指导指导,我想学习学习。

2017-11-19,望技术有成后能回来看见自己的脚步。
时间: 2024-08-03 23:36:46

ASP.NET MVC下自定义错误页和展示错误页的几种方式的相关文章

ASP.NET MVC 下自定义 JsonResult,使用 Json.NET 序列化 JSON

直接贴代码了: using System; using System.Web.Mvc; using Newtonsoft.Json; namespace MvcSample.Extensions { public class ConverterJsonResult : JsonResult { #region Fields private readonly JsonConverter[] _converters; #endregion #region Ctor public ConverterJ

asp.net mvc输出自定义404等错误页面,非302跳转。

朋友问到一个问题,如何输出自定义错误页面,不使用302跳转.当前页面地址不能改变. 还要执行一些代码等,生成一些错误信息,方便用户提交反馈. 500错误,mvc框架已经有现成解决方法: filters.Add(new HandleErrorAttribute()); 404错误目前想到的解决方法: 先上代码 Global.asax: 1 protected void Application_Error(object sender, EventArgs e) 2 { 3 var ex = Serv

ASP.NET MVC下的四种验证编程方式

原文:ASP.NET MVC下的四种验证编程方式 ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性,我们将针对参数的验证成为Model绑定.总地来说,我们可以采用4种不同的编程模式来进行针对绑定参数的验证. 目录 一.手工验证绑定的参数 二.使用ValidationAttribute特性 三.让数据类型实现IValidatableObject接口 四.让数据类型实现IDataError

ASP.NET MVC下的四种验证编程方式【转】

ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效 性,我们将针对参数的验证成为Model绑定.总地来说,我们可以采用4种不同的编程模式来进行针对绑定参数的验证. 目录 一.手工验证绑定的参数 二.使用ValidationAttribute特性 三.让数据类型实现IValidatableObject接口 四.让数据类型实现IDataErrorInfo接口 一.手工验证绑定的参数 在 定义具

在ASP.NET MVC下有关上传图片脏数据的解决方案

在"在ASP.NET MVC下实现单个图片上传, 客户端服务端双重限制图片大小和格式, 服务端裁剪图片"中,已经实现了在客户端和服务端限制图片大小和格式,以及在服务端裁剪图片.但还有一个重要的话题是需要面对的,那就是图片脏数据问题. 假设用户添加产品信息,并且上传了图片,可之后用户没有点击页面上的添加按钮,这就导致上传图片成为"脏数据",存在着却一直不会被使用.解决这个问题的大致思路是: ○ 在上传图片的时候,把图片保存到一个临时文件夹,或者叫缓存文件夹○ 当用户真

ASP.NET MVC下的四种验证编程方式[续篇]

在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注ValidationAttribute特性"."让数据类型实现IValidatableObject或者IDataErrorInfo"),那么在ASP.NET MVC框架内部是如何提供针对这四种不同编程方式的支持的呢?接下来我们就来聊聊这背后的故事. 一.ModelValidator与ModelVal

在ASP.NET MVC下通过短信验证码注册

以前发短信使用过短信猫,现在,更多地是使用第三方API.大致过程是: → 用户在页面输入手机号码→ 用户点击"获取验证码"按钮,把手机号码发送给服务端,服务端产生几位数的随机码,并保存在某个地方(Session, Applicaiton, 数据库, 等等),调用第三方的API→ 第三方发送几位数的随机码至用户手机→ 用户在页面输入接收到的随机码→ 把随机码等发送给服务端,与服务端保存的随机码比较,如果一致,就通过,让注册 就按如下界面来说吧: 我们需要考虑的方面包括: ● 手机号码:判

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

[译]Asp.net MVC 利用自定义RouteHandler来防止图片盗链 你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你的服务器带宽.下面这种方法可以告诉你如何在ASP.NET MVC中实现一个自定义RouteHandler来防止其他人盗链你的图片. 首先,我们来回顾一下当一个请求发往ASP.net MVC站点时的情景,IIS收到请求并将请求转到ASP.net,然后根据URL,或者更确切来说:被请求文件的扩展名.在IIS

Asp.net MVC 出现“Failed to map the path &#39;/&#39;.”错误

Server Error in '/' Application. Parser Error Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. Parser