ASP.NET MVC Custom Error Pages with Magical Unicor

2019-02-23 01:09发布

问题:

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.

回答1:

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:-)



回答2:

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. :)