ASP.NET MVC Custom Error Pages with Magical Unicorn
Asked Answered
M

2

5

my question is regarding Pure.Kromes answer to this post. I tried implementing my pages' custom error messages using his method, yet there are some problems I can't quite explain.

a) When I provoke a 404 Error by entering in invalid URL such as localhost:3001/NonexistantPage, it defaults to the ServerError() Action of my error controller even though it should go to NotFound(). Here is my ErrorController:

    public class ErrorController : Controller
    {
        public ActionResult NotFound()
        {
            Response.TrySkipIisCustomErrors = true;
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            var viewModel = new ErrorViewModel()
            {
                ServerException = Server.GetLastError(),
                HTTPStatusCode = Response.StatusCode
            };
            return View(viewModel);
        }

        public ActionResult ServerError()
        {
            Response.TrySkipIisCustomErrors = true;
            Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            var viewModel = new ErrorViewModel()
            {
                ServerException = Server.GetLastError(),
                HTTPStatusCode = Response.StatusCode
            };
            return View(viewModel);
        }
    }

My error routes in Global.asax.cs:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

        routes.MapRoute(
            name: "Error - 404",
            url: "NotFound",
            defaults: new { controller = "Error", action = "NotFound" }
            );

        routes.MapRoute(
            name: "Error - 500",
            url: "ServerError",
            defaults: new { controller = "Error", action = "ServerError" }
            );


And my web.config settings:

<system.web>
    <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/ServerError">
    <error statusCode="404" redirect="/NotFound" />
</customErrors>
...
</system.web>

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" subStatusCode="-1" />
      <error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
</httpErrors>
...

The Error views are located in /Views/Error/ as NotFound.cshtml and ServerError.cshtml.

b) One funny thing is, When a server error occurs, it does in fact display the Server Error view I defined, however it also outputs a default error message as well saying that the Error page could not be found.

Here's how it looks like:


Do you have any advice how I could fix these two problems? I really like Pure.Kromes approach to implementing these error messages, but if there are better ways of achieving this don't hestitate to tell me.

Thanks!

**EDIT : ** I can directly navigate to my views through the ErrorController by accessing /Error/NotFound or Error/ServerError.

The views themselves only contain some text, no markup or anything.

As I said, it actually works in some way, just not the way I intended it to work. There seems to be an issue with the redirect in the web.config, but I haven't been able to figure it out.

Meyerbeer answered 31/10, 2012 at 10:27 Comment(3)
Can you post your views too? Also don't forget to remove this GlobalFilters.Filters.Add(new HandleErrorAttribute());Abbotsun
Can you navigate directly to your 404 page?Triumvir
Yes I can. The issue here seems to originate from the settings in the web.config, though I can't find the mistake there.Meyerbeer
M
0

I got it to work. It seems my understanding of the problem was somewhat wrong to begin with.

In the web.config, I changed the following:

<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Views/Error/ServerError.cshtml">
  <error statusCode="404" redirect="~/Views/Error/NotFound.cshtml" />
</customErrors>

... and ...

<httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" subStatusCode="-1" />
      <error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
    </httpErrors>

This directly redirects to the views. My understanding was that I had to redirect to the error controller which in turn would redirect to the views, but apparently this was not the case. I'd like to thank you for your comments as they have made me analyze the problem again when I was already about to just ditch the custom error stuff and simply be lazy and display YSOD's. :)

Meyerbeer answered 12/11, 2012 at 8:33 Comment(0)
N
2

there is one more issue with that setup, when you have more complex routes and have several segments ex.

http://localhost:2902/dsad/dadasdmasda/ddadad/dadads/ddadad/dadadadad/

I got server error ->

Sorry, an error occurred while processing your request.


Exception: An error occured while trying to Render the custom error view which you provided, for this HttpStatusCode. ViewPath: ~/Views/Error/NotFound.cshtml; Message: The RouteData must contain an item named 'controller' with a non-empty string value.
Source: 

my solution for that was to add additional route at the end after default route

        routes.MapRoute(
            "Default Catch all 404",
            "{controller}/{action}/{*catchall}",
            new { controller = "Error", action = "NotFound" }
        );

hope it could help someone:-)

Neille answered 19/12, 2012 at 17:2 Comment(1)
You are correct. I'll incorporate this into my routes as well. Thanks!Meyerbeer
M
0

I got it to work. It seems my understanding of the problem was somewhat wrong to begin with.

In the web.config, I changed the following:

<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Views/Error/ServerError.cshtml">
  <error statusCode="404" redirect="~/Views/Error/NotFound.cshtml" />
</customErrors>

... and ...

<httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" subStatusCode="-1" />
      <error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
    </httpErrors>

This directly redirects to the views. My understanding was that I had to redirect to the error controller which in turn would redirect to the views, but apparently this was not the case. I'd like to thank you for your comments as they have made me analyze the problem again when I was already about to just ditch the custom error stuff and simply be lazy and display YSOD's. :)

Meyerbeer answered 12/11, 2012 at 8:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.