新西兰程序员 ASP.NET网站中设置404自定义错误页面
ASP.NET网站中设置404自定义错误页面
在用ASP.NET WebForm开发一个网站时,需要自定义404错误页面. 做法是这样的
在网站根目录下建立了一个404.html的错误页面,然后在Global.asax文件中,加入如下代码:

<%@ Application Language="C#" %> <script runat="server"> void Application_Error(object sender, EventArgs e)
{
Response.StatusCode = 404;
Server.Transfer("/404.html");
Server.ClearError();
}
</script>

然后运行网站,比如随便输入一个111.aspx时,发现在chrome上会自动redirect到这个404.html, 但是在IE上时,却不会。
在网上查找原因,找到如下答案:
果然,在这个页面中加入一些内容后,这个问题就解决了
另外,这种设置404错误页面,还有一个问题就是,当你在网址中输入不存在的比如111.aspx时,它会自动转入自定义的404.html
但是当你在网址中输入不存在的111, 没有后缀名aspx时,它就不会显示自定义的404.html了
为什么会出现这种情况呢 ? 应该怎么解决呢 ?
解决方法: 你需要在web.config中进行配置,在 <system.webServer>配置节点中加入如下语句
<httpErrors errorMode="Custom" existingResponse="Replace">
<clear />
<error statusCode="404" path="404.html" />
</httpErrors>
详细的处理ASP.NET网站自定义错误页面方法,可以参考如下这篇文章,写的很好
转载自 http://edi.wang/post/2014/1/11/iis7-aspnet-custom-error-best-practice
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
针对IIS7以上的ASP.NET网站自定义错误页面与异常日志总结
自定义错误页面和异常记录是个很古老的话题了,但依旧可以让人爆到现在。在我做了无数次试验并总结经验和原则后,写下本文,已警后人。
本文的范围和限制
- 本文仅仅适用于部署在IIS7或以上版本中的ASP.NET 4.0集成模式应用程序。IIS7以上的意思是Windows Server 2008以上服务器适用。我已在WS2012R2,IIS8上测过。
- 本文的方法均适用于ASP.NET WebForm和MVC应用程序。
本文针对的问题
- 静态错误页面好还是动态错误页面好?我该如何设计ASP.NET网站错误处理?
- 我不希望错误页面后面跟上aspxerrorpath=…这个小尾巴。
- 我的自定义错误页面在VS里调试是好的,为什么部署到服务器上就出不来了?
- 我的自定义错误页面可以正常显示,但为什么返回的Http状态码不正确?
- 异常日志该怎样记录,有没有比较好的实践?
一、错误页面的选择
选择静态html页面作为错误页,还是使用.aspx或是MVC View来显示错误页面好?这个问题许多人的偏好都不一样。我强烈建议大家用html静态页面作为错误页。请看分析:
首先,用动态页面的人,无非是为了解决三个问题:显示错误摘要、记录日志、返回正确的状态码。但是,动态页面最大的问题在于,它们本身是要经过ASP.NET和后台代码处理的,万一你的后台代码是爆的,或者ASP.NET自己爆了,那你的错误页面一旦被请求,本身就会引发另一个错误。而静态html是不会有这个问题的。至于在MVC里专门建一个ErrorController的做法就更不可取了。MVC是基于ASP.NET之上的,MVC的Controller只能抓MVC自己的错误,抓不到ASP.NET的错误,意思就是说,当你的错误并不在MVC层面上的时候,ErrorController没有任何用武之地。例如,当你部署的MVC应用程序缺少MVC的dll时候,MVC框架本身都跑不起来,这个错误如何去抓?
另外,我认为在一个Internet站点上,绝不应该向访客显示任何的错误摘要。这是非常不安全的。所以完全没有必要用动态页面。
至于返回正确状态码的问题是这样的:不少小伙伴发现自己的错误页面能够显示,但返回的状态码是200OK,所以无奈之下用动态页面,写上Response.StatusCode = 500这样的代码来强撸。这个在稍后的文章里有解决方案,所以不要为了状态码而冒险用动态页面。有的小伙伴会问,我只写一笔Response.StatusCode=500能有什么风险?呵呵,想想这种情况:404.cshtml,razor引擎的dll不见了……
另外,一个原则是:错误页面应当是独立的。如果你的静态页面要用到图片和CSS等外部资源,建议嵌入在页面里边,做成单文件的,以免显示错误页面时请求相关资源再次引发异常。小伙伴又要问了,请求个CSS和图片什么的,肿么会引发异常呢?那你看看这个:resources.axd?image=…,呵呵。
那么用了静态页面以后,记录日志怎么办呢?正确的方法应该是交给Global.asax中的“Application_Error”事件处理。稍后会有翔解。
二、配置错误页面:customErrors VS httpErrors
首先,错误页面的显示方式有两种。如果你打开IIS,会看到两个配错误页的地方:.NET Error Pages和Error Pages。
站在开发者的角度来说,ASP.NET Section下的“.NET Error Pages”就是web.confg/system.web/customErrors节点。而IIS Section下的”Error Pages”是web.config/system.webServer/httpErrors节点,这个是IIS7以上特有的。
任何在IIS上对这两处的更改其实都是在修改web.config文件。
那么我们该用哪一个来配置自定义错误页呢?我的一个原则是:让IIS向用户展示错误页面,而不要依赖于ASP.NET。 猿因如下:
CustomError的问题:
a) 在默认情况下,CustomError会采用302重定向的方式来展示错误页面,如果客户端请求了一个404的页面,那它得到的将会是一个302紧接着一个200OK,对于人类来说这是OK的,毕竟用户看到了友好的错误页面,但搜索引擎会认为这个不存在的地址是正常的页面,并把你的404页面收入搜索结果。并且每次引发错误,URL后边都会跟上aspxerrorpath这个小尾巴,比如:
http://yoursite.com/404.html?aspxerrorpath=/somethingnotexsit
b) 在配置了redirectMode=“ResponseRewrite”后,会引发一个问题,09年就有人当bug提交到MS Connect上了,但目前微软不打算fix这个bug。即该模式在VS自带的ASP.NET Development Server上是有效的,浏览器显示的是解析后的HTML页面,而部署到IIS上之后,浏览器显示是raw html,即你的错误页面的HTML代码。并且该行为不具有确定性,天晓得你的网站换个环境部署又会爆成什么样。
c) IIS7以上版本的特殊性:在集成模式下,IIS的错误页面会优先于ASP.NET错误页面,即IIS的默认错误页会覆盖你配置的CustomErrors页面,这就是为什么你在VS下调试是好的,部署到服务器上就爆了。
在IIS7之后,取决于你的配置,用户的请求并不都一定在ASP.NET管线上处理。如果引发异常的地方不在ASP.NET,那就不会显示CustomErrors的错误页面。
所以,我强烈建议大家用httpErrors节点替代CustomErrors来配置错误页面。
三、File还是ExecuteURL:httpErrors的正确配法
先贴一个正确的配置样例:是用File配的。
注意两处地方:
- 斜杠是Windows文件路径的反斜杠“\”而不是网址URL的斜杠“/”
- Path不要以“~”或“\”开头
不要问我为什么,我也不知道,反正这么弄就是好的。
如果你不幸用了ExecuteURL,你会发现URL路径只能以“/”开头:
并且你的错误页会返回200OK而不是正确的404、500等错误码。这在我以前的文章里写过:
而用File的意思是,当错误被爆出来之后,IIS会把目标File,比如404.html的内容,塞到当前的Response流里面,保持Http状态码依旧是404。这就是我们想要的。
四、异常日志记录
文章在一开始就提了个问题,木有了动态页面,怎么记录错误日志?我的做法是在Global.asax里处理。
Application_Error事件样例代码如下:

var exception = HttpContext.Current.Server.GetLastError(); if (null != exception)
{
// by default 500
var statusCode = (int)HttpStatusCode.InternalServerError; if (exception is HttpException)
{
statusCode = new HttpException(null, exception).GetHttpCode();
}
else if (exception is UnauthorizedAccessException)
{
// to prevent login prompt in IIS
// which will appear when returning 401.
statusCode = (int)HttpStatusCode.Forbidden;
} if ((LogHttpNotFound && statusCode == 404) || statusCode != 404)
{
if (null != _loggerFunc)
{
LoggerFunc(string.Format("ASP.NET Error Captured, Request URL: {0}, Exception:",
HttpContext.Current.Request.Url), exception);
}
} ExceptionInfo = exception.Message;
_statusCode = statusCode; }

一个小小的建议是不要记录404错误,因为你的网站在Internet上会被各种搜索引擎、扫描工具和黑客菊爆,有一种攻击手段是通过字典猜解目录,返回404就是不存在,返回403就是存在。所以,当你碰到这种无聊黑客的时候,如果记录了404请求,那你的日志会非常的大……
我记日志用的组件是NLog,配置简单,使用容易。Log4net这货已经好久没更新了。
如果你决定自己设计日志模块,那要记住两个原则:
日志模块本身并不能因为自己爆掉而影响整个系统运行,即任何在日志模块里的异常不应该向外冒泡。
考虑并发写日志的情况,日志操作应该是Fire and Forget的,不能让应用程序等待日志写入。
五、总结
- 采用静态html页面作为错误页。
- 采用httpErrors配置错误页面,目的是兼容IIS7以上环境、返回正确错误码、去掉aspxerrorpath小尾巴。
- 日志记录写在Global.asax里,在Application_Error事件中记录
原文:http://www.cnblogs.com/wphl-27/p/6014654.html
新西兰程序员 ASP.NET网站中设置404自定义错误页面的更多相关文章
- ASP.NET网站中设置404自定义错误页面
在用ASP.NET WebForm开发一个网站时,需要自定义404错误页面. 做法是这样的 在网站根目录下建立了一个404.html的错误页面,然后在Global.asax文件中,加入如下代码: &l ...
- 在Tomcat中配置404自定义错误页面详解
这篇文章主要介绍了在Tomcat中配置404自定义错误页面全解,需要的朋友可以参考下 一直使用tomcat,今天想到一个问题,自定义404错误页面, 为了获得很好的用户感受,是不应当向用户暴露404这 ...
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- ASP.NET网站中获取当前虚拟目录的应用程序目录的方法(转)
[原创]ASP.NET网站中获取当前虚拟目录的应用程序目录的方法 ASP.NET网站中获取当前虚拟目录的应用程序目录的方法1.问题描述:有时候,某个网页控件会被不同目录下文件使用,此时如果该控件中有一 ...
- ASP.NET应用程序和ASP.NET网站所共有的文件: App_Browsers 等
App_Browsers 包含 ASP.NET 用于标识个别浏览器并确定其功能的浏览器定义 (.browser) 文件.有关更多信息,请参见浏览器定义文件架构(browsers 元素)和如何:在 A ...
- VS2010 Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)
步骤如下: 1. Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)" title="VS2010 Chart控件(一)Chart控件在ASP.NE ...
- ASP.NET MVC中设置跨域
ASP.NET MVC中设置跨域 1.什么是跨域请求 js禁止向不是当前域名的网站发起一次ajax请求,即使成功respone了数据,但是你的js仍然会报错.这是JS的同源策略限制,JS控制的并不是我 ...
- js基础 js自执行函数、调用递归函数、圆括号运算符、函数声明的提升 js 布尔值 ASP.NET MVC中设置跨域
js基础 目录 javascript基础 ESMAScript数据类型 DOM JS常用方法 回到顶部 javascript基础 常说的js包括三个部分:dom(文档document).bom(浏览器 ...
- 漫谈程序员(十八)windows中的命令subst
漫谈程序员(十八)windows中的命令subst 用法格式 一.subst [盘符] [路径] 将指定的路径替代盘符,该路径将作为驱动器使用 二.subst /d 解除替代 三.不加任何参数键入 ...
随机推荐
- 后台向前台响应的json数据格式的一些问题
最近在写后台向前台easyUI页面发送数据时遇到的一些报错. 首先easyUI内部封装了许多的方法和对象,以至于很多参数都不清楚,需要查询,其次easyUI也是有内置ajax所以从后台响应回来的数据一 ...
- mybatis逆向工程(eclipse版本)
1. 新建maven项目, 目录结构 2. src/main/resources中新建generatorConfig.xml <?xml version="1.0" enco ...
- django中解决跨域问题
-跨域问题 -浏览器的:同源策略,浏览器拒绝不是当前域域返回的数据 -ip地址和端口号都相同才是同一个域 -如何解决: -CORS:跨域资源共享 -简单请求:发一次请求 -非简单请求:非简单请求是发送 ...
- 使用C#的Flags特性
举个例子:我有如下的一个需求,当我想要取得用户信息的时候,会先从本地缓存中查找,找不到然后从分布式缓存中查找,最后找不到再从数据库中查询.但是有些场景我又不需要查询数据库. 所以我想建立如下这种模型. ...
- 用Python做一个飞机大战游戏
基于pygame的一款小游戏 这是我上半年做的一款小游戏,但是一直忘记了,现在才上传代码. github项目地址:StarMan 代码基于pygame,Python版本3.5.2运行正常. 游戏很简单 ...
- css选择器学习(一)
1.通用选择器“*”和元素选择器 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- jq监听页面的滚动事件,
jQuery监听页面的滚动状态,实现代码: $(document).scroll(function() { var scroH = $(document).scrollTop(); //滚 ...
- 遍历windows窗口
原文 1. GetDesktopWindow GetNextWindow HWND hAll = ::GetDesktopWindow(); HWND hCurrent = ::GetNextWind ...
- Python中的if和while
if 判断 if形式有三种: 1.if ... 2.if ... else ... 3.if ... elif ... else ... 实例: inp = raw_input('>>&g ...
- javascript逻辑与(&&)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...