昨天在码页面的时候手写了一次AJAX,蛋都碎了,顺便发现了一个问题。我在ajax的脚本里检查http的返回状态是不是200OK以此来判断ajax是否执行成功。结果发现网站里所有的404、500页面均返回200OK,我蛋都碎了。用Firebug检查了一下,确实如此。这是自定义错误页的问题。如果用了html静态页作为错误页,比如404.html,通常我们的web.config里会这样写:

<httpErrors errorMode="Custom" existingResponse="Replace" defaultResponseMode="ExecuteURL">
  <remove statusCode="404" subStatusCode="-1"/>
  <remove statusCode="500" subStatusCode="-1"/>
  <error statusCode="404" path="/404.html" prefixLanguageFilePath="" responseMode="ExecuteURL"/>
  <error statusCode="500" path="/500.html" prefixLanguageFilePath="" responseMode="ExecuteURL"/>
</httpErrors>

这段配置是给IIS7的,以往写在customError里,其实问题是一样会出现的。这样写的问题就在于,如果遇到了404错误,它确实会返回我们的404.html,但状态码却不是404。这样搜索引擎会认为这是一个网站中已存在的页面并收入索引,如果被人搜到,搜索预览里会直接显示我们错误页的内容,非常傻逼,会被人笑了。不信可以用firebug检查一下:

而正确的结果应该是返回404状态码,比如在IIS默认的配置下,显示详细错误信息的时候,用的就是404状态码,有图有真相:

但我们还是希望显示友好的自定义错误页,而不返回200OK,怎么办呢。其实很简单。首先不能用html静态页面来做错误页了。如果你用了MVC3,你可以像我一样用razor写个cshtml,如果你用的是aspx视图引擎或者还是用webform开发的网站,那也没关系。原理都是一样的。

如果是cshtml,在网页头部加入这两句代码:

Response.Status = "404 Not Found";
Response.StatusCode = 404;

ASPX视图引擎则写在Page_Load事件里就可以了。

我测试用的404.cshtml如下:

@{
    Layout = null;

    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
}

<!DOCTYPE html>

<html>
<head>
    <title></title>
</head>
<body>
    <div>
        This is a custom 404 which will return real 404 status code~
    </div>
</body>
</html>

然后改一下web.config,把404指定到404.cshtml:

<error statusCode="404" path="/ErrorPages/404.cshtml" prefixLanguageFilePath="" responseMode="ExecuteURL"/>

现在再用firebug检查一下,已经没问题了,有图有真相: