自定义错误页面,当发生 Http 错误而不更改 url 时

Ram*_*dar 1 asp.net-mvc asp.net-mvc-3

当 Http 错误发生时,如何在不更改 url 的情况下显示自定义错误页面。

当发生 Http 错误时,如何显示客户自定义错误页面而不路由到另一个 URL。

Car*_*arl 7

下面的方法不会使用重定向 - 它将返回您的自定义错误 + 正确的 httpstatus 代码作为对客户端的立即响应,方法是捕获 application_error 方法中的错误,然后选择在同一响应中返回的内容,从而无需重定向。

创建一个 ErrorController - 这允许您定制最终用户错误页面和状态代码。:

[AllowAnonymous]
public class ErrorController : Controller
{
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        return View();
    }

    public ActionResult ServerError()
    {
        Response.StatusCode = 500;
        return View();
    }

    public ActionResult UnauthorisedRequest()
    {
        Response.StatusCode = 403;
        return View();
    }

    //Any other errors you want to specifically handle here.

    public ActionResult CatchAllUrls()
    {
        //throwing an exception here pushes the error through the Application_Error method for centralised handling/logging
        throw new HttpException(404, "The requested url " + Request.Url.ToString() + " was not found");
    }
}
Run Code Online (Sandbox Code Playgroud)

添加一个路由来捕获所有 url 到路由配置的末尾 - 这将捕获所有尚未通过匹配现有路由捕获的 404:

routes.MapRoute("CatchAllUrls", "{*url}", new { controller = "Error", action = "CatchAllUrls" });
Run Code Online (Sandbox Code Playgroud)

在你的 global.asax 中:

protected void Application_Error(object sender, EventArgs e)
    {
        Exception exception = Server.GetLastError();

        //Error logging omitted

        HttpException httpException = exception as HttpException;
        RouteData routeData = new RouteData();
        IController errorController = new Controllers.ErrorController();
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("area", "");
        routeData.Values.Add("ex", exception);

        if (httpException != null)
        {
            //this is a basic exampe of how you can choose to handle your errors based on http status codes.
            switch (httpException.GetHttpCode())
            {
                case 404:
                    Response.Clear();

                    // page not found
                    routeData.Values.Add("action", "PageNotFound");

                    Server.ClearError();
                    // Call the controller with the route
                    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));

                    break;
                case 500:
                    // server error
                    routeData.Values.Add("action", "ServerError");

                    Server.ClearError();
                    // Call the controller with the route
                    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
                    break;
                 case 403:
                    // server error
                    routeData.Values.Add("action", "UnauthorisedRequest");

                    Server.ClearError();
                    // Call the controller with the route
                    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
                    break;
                 //add cases for other http errors you want to handle, otherwise HTTP500 will be returned as the default.
                default:
                    // server error
                    routeData.Values.Add("action", "ServerError");

                    Server.ClearError();
                    // Call the controller with the route
                    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
                    break;
            }
        }
        //All other exceptions should result in a 500 error as they are issues with unhandled exceptions in the code
        else
        {
            routeData.Values.Add("action", "ServerError");
            Server.ClearError();
            // Call the controller with the route
            errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
        }
    }
Run Code Online (Sandbox Code Playgroud)