You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MVC HTTP错误自定义问题:自定义404页面不生效

.NET MVC 主动返回404状态码不显示自定义错误页的解决方法

问题描述

本地运行.NET MVC站点,自定义HTTP错误页面后,通过代码return new HttpStatusCodeResult(404);主动抛出404错误时,未显示预期的自定义错误页,而是出现HTTP默认错误页。相关配置代码如下:

global.asax 代码

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    bool isAjaxRequest = Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest";

    if (!isAjaxRequest)
    {
        if (exception is HttpException httpException)
        {
            int httpCode = httpException.GetHttpCode();
            if (httpCode == 404)
            {
                Response.Redirect("~/Error/NotFound");
            }
            else if (httpCode == 500)
            {
                Response.Redirect("~/Error/ServerError");
            }
            else
            {
                Response.Redirect("~/Error/Error");
            }
        }
        else
        {
            Response.Redirect("~/Error/Error");
        }
    }
}

Web.Config 配置

<customErrors mode="On" defaultRedirect="/Error/Error">
    <error statusCode="404" redirect="/Error/NotFound" />
    <error statusCode="500" redirect="/Error/ServerError" />
</customErrors>

ErrorController 代码

public class ErrorController : Controller
{
    [HttpGet]
    public ActionResult Error()
    {
        return View();
    }

    [HttpGet]
    public ActionResult NotFound() 
    {
        Response.StatusCode = 404;
        Response.TrySkipIisCustomErrors = true;
        return View();
    }

    [HttpGet]
    public ActionResult ServerError()
    {
        Response.StatusCode = 500;
        Response.TrySkipIisCustomErrors = true;
        return View();
    }
}

问题原因

return new HttpStatusCodeResult(404)仅设置响应的HTTP状态码,不会抛出HttpException异常,因此Application_Error事件无法捕获该情况,也就不会跳转到自定义错误页。同时默认的customErrors配置在主动返回状态码的场景下,可能被IIS默认错误页覆盖。

解决方案

1. 修改Web.Config的customErrors配置

添加redirectMode="ResponseRewrite",避免通过跳转(302)返回错误页,确保响应状态码保持为原错误码(如404),同时让IIS优先使用自定义错误页:

<customErrors mode="On" defaultRedirect="/Error/Error" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="/Error/NotFound" />
    <error statusCode="500" redirect="/Error/ServerError" />
</customErrors>

2. 在global.asax中添加Application_EndRequest事件处理

用于捕获主动返回的HTTP错误状态码,并重写请求到对应的错误页面:

protected void Application_EndRequest()
{
    var response = Context.Response;
    bool isAjaxRequest = Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
    
    // 只处理非Ajax、未跳转的错误状态码
    if (!isAjaxRequest && response.StatusCode >= 400 && response.StatusCode < 600 && !response.IsRequestBeingRedirected)
    {
        Server.ClearError();
        string errorPath = "/Error/Error";
        
        switch (response.StatusCode)
        {
            case 404:
                errorPath = "/Error/NotFound";
                break;
            case 500:
                errorPath = "/Error/ServerError";
                break;
        }
        
        // 重写请求而非跳转,保留原状态码
        Context.RewritePath(errorPath);
        IHttpHandler httpHandler = new MvcHttpHandler();
        httpHandler.ProcessRequest(Context);
    }
}

3. 优化Application_Error事件(可选)

原Response.Redirect会导致状态码变为302,可改为RewritePath保持原错误状态码:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    bool isAjaxRequest = Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest";

    if (!isAjaxRequest)
    {
        Server.ClearError();
        string errorPath = "/Error/Error";
        
        if (exception is HttpException httpException)
        {
            int httpCode = httpException.GetHttpCode();
            switch (httpCode)
            {
                case 404:
                    errorPath = "/Error/NotFound";
                    break;
                case 500:
                    errorPath = "/Error/ServerError";
                    break;
            }
        }
        
        Context.RewritePath(errorPath);
        IHttpHandler httpHandler = new MvcHttpHandler();
        httpHandler.ProcessRequest(Context);
    }
}

关键说明

  • ResponseRewrite模式直接渲染错误页内容,不会发送跳转指令,能保留原HTTP状态码。
  • Application_EndRequest会在每个请求结束时触发,可捕获所有未被Application_Error处理的主动返回错误状态码。
  • Response.TrySkipIisCustomErrors = true必须保留在ErrorController的对应方法中,确保IIS不会覆盖自定义错误页。

内容的提问来源于stack exchange,提问作者krautcez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 07:07:01