ASP.NET MVC 5 - Error Handle for - 404 Page not fo

2019-08-18 05:08发布

问题:

For standard errors I use solution error handle (see code below), and also I tried THIS (without effect)

Global.asax.cs

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

        var httpException = exception as HttpException;
        var routeData = new RouteData();

        routeData.Values.Add("controller", "Error");

        if (httpException == null)
            routeData.Values.Add("action", "Index");
        else //It's an Http Exception, Let's handle it.
            switch (httpException.GetHttpCode())
            {
                case 404:
                    // Page not found.
                    routeData.Values.Add("action", "HttpError404");
                    break;
                case 500:
                    // Server error.
                    routeData.Values.Add("action", "HttpError500");
                    break;

                // Here you can handle Views to other error codes.
                // I choose a General error template  
                default:
                    routeData.Values.Add("action", "General");
                    break;
            }

        // Pass exception details to the target error View.
        routeData.Values.Add("error", exception);

        var request = Request;
        // Pass request details to the target request View.
        routeData.Values.Add("request", request);

        // Clear the error on server.
        Server.ClearError();

        // Avoid IIS7 getting in the middle
        Response.TrySkipIisCustomErrors = true;

        // Call target Controller and pass the routeData.
        IController errorController = new ErrorController();
        errorController.Execute(new RequestContext(
            new HttpContextWrapper(Context), routeData));
}

ErrorController

public class ErrorController : Controller
{
    private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    // GET: Error
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult HttpError404(string error, HttpRequest request)
    {
        ViewBag.Title = "Page not found (Error 404)";
        ViewBag.Description = error;
        return View("~/Views/Shared/Error.cshtml");
    }

    public ActionResult HttpError500(string error, HttpRequest request)
    {
        ViewBag.Title = "Internal server error (Error 500)";
        ViewBag.Description = error;
        return View("~/Views/Shared/Error.cshtml");
    }

    public ActionResult General(string error, HttpRequest request)
    {
        ViewBag.Title = "Internal server error";

        ViewBag.Description = error;
        return View("~/Views/Shared/Error.cshtml");
    }
}

Error.cshtml

@{
    Layout = "_Layout.cshtml";
}

<div class="row">
    <div class="exceptionmessage col-md-12 text-center">
        <div class="center-block">
            <img src="~/Content/i/404.png" class="img-responsive"/>
        </div>

        <strong>@ViewBag.Message</strong>
        <span class="center-block small text-uppercase">@ViewBag.Main</span>


        <div class="center-block">@Html.ActionLink("Return to the Homepage", "Index", "Home", null, new {@class = "btn btn-primary"})</div>
    </div>
</div>

I have a directory Techs where I have some XML files (for load data, something like local DB), and with this script in web.config I disable access to this folder and to download files from this folder (or when I write nonexist URL or file-like www.test.com/afsdfgsdfg.pdf), I got IIS message 404 Page not found without redirection to my custom error 404 page from error handler code below.

  <system.web>    
    <customErrors mode="On" defaultRedirect="~/Error">
      <error redirect="~/Error/HttpError404" statusCode="404" />
    </customErrors>
  </system.web>

  <system.webServer>    
    <security xdt:Transform="Replace">
      <requestFiltering>
        <hiddenSegments>
          <add segment="Techs" />
        </hiddenSegments>
      </requestFiltering>
    </security>
  </system.webServer>

Is there any way how handle all errors with 404 page not found (with same page and not two different)?

Thank you

EDIT:

I add a new route for my ErrorController into RouteConfig.cs:

routes.MapRoute("Error",
                "{controller}/{action}/",
                new { controller = "Error", action = "HttpError404" });

after that I change web.config to:

<customErrors mode="On" defaultRedirect="~/Error/General">
    <error redirect="~/Error/HttpError404" statusCode="404" />
    <error redirect="~/Error/HttpError500" statusCode="500" />
</customErrors>

<httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" />
      <error
        statusCode="404"
        path="/Error/HttpError404"
        responseMode="ExecuteURL"/>
    </httpErrors>

But it still does not work, I got HTTP Error 404.0 - Not Found or HTTP Error 403.14 - Forbidden and similar messages, when I write for example:

  • web.com/Techs/
  • web.com/Techs/catalog.csv
  • web.com/Techs.pdf -> redirect to the 404 page
  • web.com/Home/c.pdf

回答1:

My solution that WORKS

I do not add any new route to RouteConfig.cs, only edit file below. Controllers which I call method without a parameter, I have been treated differently. Global.asax.cs and ErrorController use same as above.

Web.config

<system.web>   
    <customErrors mode="On" defaultRedirect="~/Error/General">
      <error redirect="~/Error/HttpError404" statusCode="403" />
      <error redirect="~/Error/HttpError404" statusCode="404" />
      <error redirect="~/Error/HttpError500" statusCode="500" />
    </customErrors>

  </system.web>

  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="403" />
      <remove statusCode="404" />
      <remove statusCode="500" />
      <error
        statusCode="403"
        path="/Error/HttpError404"
        responseMode="ExecuteURL" />
      <error
        statusCode="404"
        path="/Error/HttpError404"
        responseMode="ExecuteURL" />
      <error
        statusCode="500"
        path="/Error/HttpError500"
        responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>


回答2:

In web.config add this line

<system.web>
    <customErrors mode="On" defaultRedirect="~/ErrorHandler/Index">
        <error statusCode="404" redirect="~/ErrorHandler/NotFound"/>
    </customErrors>
<system.web/>

edit: That should cover all errors with that code...but I see that you already have that.



回答3:

You can create a folder named like Error in the home directory, then create a html error page there with your own design.

In your web config, add this:

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/Error/404.html" />
</customErrors>

This would redirect to that 404.html in the Error folder.

If you want to check for specific errors in the controller and redirect to the related error pages, you can create an ErrorController in the controller and the views for the different types of errors you want to check for in the Error views folder. eg:

    //In the ErrorController
    // GET: /Error/404 Bad request
    public ActionResult E404()
    {
        return View();
    }

and in the controller if page is not found or id == null you can do something like:

if (id == null)
{
    return RedirectToAction("E404", "Error");
}