Fred Johnson
Fred Johnson

Reputation: 2695

How do you use custom errors and preserve the response code?

in my web.config blow you can see redirectMode="ResponseRewrite". I read this is what I need to preserve the status code. Unfortunately as soon as I have it in, I get:

"An exception occurred while processing your request. Additionally, another exception occurred while executing the custom error page for the first exception. The request has been terminated."

Omitting this variable successfully redirects me to ~/Error/Index.cshtml but has a response of 200. doh. Any direction would be hugely appreciated, thanks.

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Error/Index">
      <error statusCode="404" redirect="~/Error/Index"/>
      <error statusCode="500" redirect="~/Error/Index"/>
    </customErrors>
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
      <remove statusCode="403"/>
      <remove statusCode="404"/>
      <remove statusCode="500"/>
      <error statusCode="403" path="~/Error/Index" responseMode="File"/>
      <error statusCode="404" path="~/Error/Index" responseMode="File"/>
      <error statusCode="500" path="~/Error/Index" responseMode="File"/>
    </httpErrors>
  </system.webServer>

In my filterconfig.cs:

public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // does this conflict?
            filters.Add(new HandleErrorAttribute());
        }
    }

Upvotes: 6

Views: 2240

Answers (1)

George Phillipson
George Phillipson

Reputation: 860

Cannot remember where I saw this code, or what I changed, but it works fine in my MVC web app

Web.config

<system.web>
    <compilation debug="true" targetFramework="4.5.1" />
    <httpRuntime targetFramework="4.5.1" />
    <customErrors mode="Off" />
  </system.web>

Global.aspx

protected void Application_EndRequest(Object sender, EventArgs e)
        {
            ErrorConfig.Handle(Context);
        }

ErrorConfig.cs

namespace Web.UI.Models.Errors
{
    public static class ErrorConfig
    {
        public static void Handle(HttpContext context)
        {
            switch (context.Response.StatusCode)
            {
                case 401:
                    Show(context, 401);
                    break;
                case 404:
                    Show(context, 404);
                    break;
                case 500:
                    Show(context, 500);
                   break;
            }
        }
        //TODO uncomment 500 error
        static void Show(HttpContext context, Int32 code)
        {
            context.Response.Clear();

            var w = new HttpContextWrapper(context);
            var c = new ErrorController() as IController;
            var rd = new RouteData();

            rd.Values["controller"] = "Error";
            rd.Values["action"] = "Index";
            rd.Values["id"] = code.ToString(CultureInfo.InvariantCulture);

            c.Execute(new RequestContext(w, rd));
        }
    }
}

ErrorController

public class ErrorController : Controller
    {
        // GET: Error
        [HttpGet]
        public ViewResult Index(Int32? id)
        {
            var statusCode = id.HasValue ? id.Value : 500;
            var error = new HandleErrorInfo(new Exception("An exception with error " + statusCode + " occurred!"), "Error", "Index");

            int errorCode = statusCode;
            ViewBag.error = errorCode;
            return View("Error");
        }
    }

ErrorsViewModel

namespace Web.UI.Models.Errors
{
    public class ErrorViewModel
    {
        public string DisplayErrorMessage   { get; set; }
        public string DisplayErrorPageTitle { get; set; }
    }
}

Then in shared folder error page add

@model Web.UI.Models.Errors.ErrorViewModel

@{
    int errorCode = Convert.ToInt32(@ViewBag.error);


    switch (errorCode)
    {
        case 404:
            ViewBag.Title = "404 Page Not Found";
            Html.RenderPartial("~/Views/Shared/ErrorPages/HttpError404.cshtml");
            break;
        case 500:
            ViewBag.Title = "Error Occurred";
            Html.RenderPartial("~/Views/Shared/_Error.cshtml");
            break;
        default:
            ViewBag.Title = @Model.DisplayErrorPageTitle;
            Html.RenderPartial("~/Views/Shared/ErrorPages/HttpNoResultsFound.cshtml");
            break;
    }
} 

The above returns 404 status for page not found and 500 for error, hope it helps

Upvotes: 1

Related Questions