使用ASP.NET MVC处理全局和HTTP异常

3
我正在尝试使用Global.asax文件中的Application_Error()事件,在Asp.Net MVC中使用自定义错误页面来处理全局(StatusCode 500)和http异常,并使用适当的HTTP状态代码。为了简化,实际上我只有一个用于所有类型已处理异常的相同视图错误。
现在的问题是,当处理500异常时,它第一次进入Application_Error的else部分,然后返回if部分,最终返回404 http异常而不是500异常。我该如何解决这个问题?当处理500异常时,如何停止在进入Application_Error的else部分后继续运行?
以下是我的配置: web.config
<system.web>
   <customErrors mode="Off"/>
</system.web>

 <system.webServer>
      <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="400"/>
        <remove statusCode="401"/>
        <remove statusCode="403"/>
        <remove statusCode="404"/>
        <remove statusCode="500"/>
        <error statusCode="400" responseMode="ExecuteURL" path="/Error"/>
        <error statusCode="401" responseMode="ExecuteURL" path="/Error"/>
        <error statusCode="403" responseMode="ExecuteURL" path="/Error"/>
        <error statusCode="404" responseMode="ExecuteURL" path="/Error"/>
        <error statusCode="500" responseMode="ExecuteURL" path="/Error"/>
      </httpErrors>
</system.webServer>

Method Application_Error():

public void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
        HttpException httpException = exception as HttpException;

        // Clear the response stream
        HttpContext httpContext = ((HttpApplication)sender).Context;
        httpContext.Response.Clear();
        httpContext.ClearError();

        var routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Error");
        routeData.Values.Add("exception", exception);


        if (exception.GetType() == typeof(HttpException)) //It's an Http Exception
        {
            routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());

            switch (routeData.Values["statusCode"])
            {
                case 400:
                    routeData.Values.Add("status", "400 - Bad Request");
                    break;
                case 401:
                    routeData.Values.Add("status", "401 - Access Denied");
                    break;
                case 403:
                    routeData.Values.Add("status", "403 - Forbidden");
                    break;
                case 404:
                    routeData.Values.Add("status", "404 - Page Not Found");
                    break;
                case 500:
                default:
                    routeData.Values.Add("status", "500 - Internal Server Error");
                    break;
            }
        }
        else
        {
            routeData.Values.Add("statusCode", 500);
            routeData.Values.Add("status", "500 - Internal Server Error");

        }

        // Avoid IIS7 getting in the middle
        httpContext.Response.TrySkipIisCustomErrors = true;

        // Call target Controller and pass the routeData.
        IController controller = new ErrorController();
        controller.Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
        Response.End();
        // clear error on server
        //Server.ClearError();
    }

控制器 ErrorController:

public class ErrorController : Controller
    {
        // GET: /Error/
        public ActionResult Error(int statusCode, string status, Exception exception)
        {
            Response.StatusCode = statusCode;
            ViewBag.StatusCode = statusCode;
            ViewBag.Status = status;
            return View();
        }
    }
1个回答

0

这是因为应用程序抛出的Exception类型并不总是HttpException。它可能是SQLException、SystemException、IndexOutOfRangeException等等。而状态码总是仅与HttpExceptions相关联的。这就是为什么你的代码首先进入else部分,然后进入if部分的原因。

虽然它不应该再次进入if部分,但如果它确实进入了,那么你必须检查你重定向用户的页面是否会进一步抛出任何其他异常。

我还建议从你的代码中删除最后一个参数,因为Exception是一个复杂的类型,我们通常不会在Get请求中传递复杂的类型。

转换此内容

public ActionResult Error(int statusCode, string status, Exception exception)

public ActionResult Error(int statusCode, string status)

感谢您的回复。 - Chabana10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接