1

I triedd all possible ways I found either here (How to make custom error pages work in ASP.NET MVC 4) or here: http://benfoster.io/blog/aspnet-mvc-custom-error-pages, here: http://www.secretgeek.net/custom_errors_mvc but none seems to be working for me.

I simplified it to the minium, but still geting ugly standard error message when hitting page that does not exist.

My Error.cshtml is placed in Views\Shared folder and it looks like:

<div>
    <span>Error occurred</span>
</div>

tried also:

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = "Parking & Ticket Scan Information - Error";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
    <span>Error occurred</span>
</div>

My web.config contains:

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

but I tried also:

<customErrors mode="On" defaultRedirect="~/Error">
</customErrors>

My ErrorController is like:

public class ErrorController : Controller
{
    [HandleError]
    public ViewResult Index()
    {
        return View();
    }
}

(with or without [HandleError] attribute, with and without

public ViewResult NotFound()
{
    Response.StatusCode = 404;  //you may want to set this to 200
    return View("NotFound");
}

Later I added also routing in Global.asax:

routes.MapRoute( name: "PageNotFound", url: "{*url}", defaults: new { controller = "Error", action = "Index", id = UrlParameter.Optional }

Nothing seems to force IIS to show custom error. What else did I try? Of course commented out filters.Add(new HandleErrorAttribute()); Moved Error.cshtml to Views folder.

Are there any other approaches I could use to enable it?

mason
  • 31,774
  • 10
  • 77
  • 121
Radek Strugalski
  • 560
  • 7
  • 22
  • I've tried Ben Foster's solution and it works. Some of the other solutions I've tried does not work if IIS intercepts the error first -- in which case your app won't get to handle the error and you'll see the default one. – Jasen Jul 19 '17 at 19:12

2 Answers2

0

You could always do something like this

public class HandleUnauthorizedAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);

        if (filterContext.Exception.GetType() != typeof (SecurityException)) return;

        var controllerName = (string) filterContext.RouteData.Values["controller"];
        var actionName = (string) filterContext.RouteData.Values["action"];
        var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

        filterContext.Result = new ViewResult
        {
            ViewName = "Unauthorized",
            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
            TempData = filterContext.Controller.TempData
        };
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = 403;
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

This code captures all SecurityExceptions and routes then to a custom error page with the HandleErrorInfo populated.

You could always create separate filters for whatever exceptions you are looking to trap and route to other custom error pages.

Then register the filters at startup

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleUnauthorizedAttribute());
        //more filters if you define them.
    }
}

And create your view(s) in /Shared/Views

Fran
  • 6,440
  • 1
  • 23
  • 35
0

So the only possible solution I found so far was to add a view corresponding to a action method name of the ErrorController inside View\Error folder. This tiny little detail seems to be missing in all other guides.

So now I have the ErrorContoller.cs:

public class ErrorController : Controller
{
    public ActionResult ErrorDefault()
    {
        return View();
    }
}

And ErrorDefault.cshtml in Views\Error folder:

@{
    ViewBag.Title = "ErrorDefault";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>ErrorDefault</h2>

And web.config:

<customErrors mode="On" defaultRedirect="~/Error/ErrorDefault">
</customErrors>

If you forget to put your view in the subfolder corresponding to the controller name it will just not work in MVC 4.0.

Adding a separate Route in RouteConfig is not necessary.

I hope somebody will find this useful. :)

Radek Strugalski
  • 560
  • 7
  • 22
  • "If you forget to put your view in the subfolder corresponding to the controller name it will just not work in MVC" - it was always this way. – Tomas Voracek Aug 12 '17 at 17:32