How can I properly handle 404 in ASP.NET MVC?

后端 未结 19 2727
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-21 10:14

I am using RC2

Using URL Routing:

routes.MapRoute(
    \"Error\",
     \"{*url}\",
     new { controller = \"Errors\", action = \"N         


        
19条回答
  •  广开言路
    2020-11-21 10:31

    Dealing with errors in ASP.NET MVC is just a pain in the butt. I tried a whole lot of suggestions on this page and on other questions and sites and nothing works good. One suggestion was to handle errors on web.config inside system.webserver but that just returns blank pages.

    My goal when coming up with this solution was to;

    • NOT REDIRECT
    • Return PROPER STATUS CODES not 200/Ok like the default error handling

    Here is my solution.

    1.Add the following to system.web section

       
         
          
          
         
        
    

    The above handles any urls not handled by routes.config and unhandled exceptions especially those encountered on the views. Notice I used aspx not html. This is so I can add a response code on the code behind.

    2. Create a folder called Error (or whatever you prefer) at the root of your project and add the two webforms. Below is my 404 page;

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="404.aspx.cs" Inherits="Myapp.Error._404" %>
    
    
    
    
        
        
        Page Not found
        " rel="stylesheet" />
    
    
        

    404 - Page Not found

    The page you are looking for cannot be found.


    And on the code behind I set the response code

    protected void Page_Load(object sender, EventArgs e)
    {
        Response.StatusCode = 404;
    }
    

    Do the same for the 500 page

    3.To handle errors within the controllers. There's many ways to do it. This is what worked for me. All my controllers inherit from a base controller. In the base controller, I have the following methods

    protected ActionResult ShowNotFound()
    {
        return ShowNotFound("Page not found....");
    }
    
    protected ActionResult ShowNotFound(string message)
    {
        return ShowCustomError(HttpStatusCode.NotFound, message);
    }
    
    protected ActionResult ShowServerError()
    {
        return ShowServerError("Application error....");
    }
    
    protected ActionResult ShowServerError(string message)
    {
        return ShowCustomError(HttpStatusCode.InternalServerError, message);
    }
    
    protected ActionResult ShowNotAuthorized()
    {
        return ShowNotAuthorized("You are not allowed ....");
    
    }
    
    protected ActionResult ShowNotAuthorized(string message)
    {
        return ShowCustomError(HttpStatusCode.Forbidden, message);
    }
    
    protected ActionResult ShowCustomError(HttpStatusCode statusCode, string message)
    {
        Response.StatusCode = (int)statusCode;
        string title = "";
        switch (statusCode)
        {
            case HttpStatusCode.NotFound:
                title = "404 - Not found";
                break;
            case HttpStatusCode.Forbidden:
                title = "403 - Access Denied";
                break;
            default:
                title = "500 - Application Error";
                break;
        }
        ViewBag.Title = title;
        ViewBag.Message = message;
        return View("CustomError");
    }
    

    4.Add the CustomError.cshtml to your Shared views folder. Below is mine;

    @ViewBag.Title


    @ViewBag.Message

    Now in your application controller you can do something like this;

    public class WidgetsController : ControllerBase
    {
      [HttpGet]
      public ActionResult Edit(int id)
      {
        Try
        {
           var widget = db.getWidgetById(id);
           if(widget == null)
              return ShowNotFound();
              //or return ShowNotFound("Invalid widget!");
           return View(widget);
        }
        catch(Exception ex)
        {
           //log error
           logger.Error(ex)
           return ShowServerError();
        }
      }
    }
    

    Now for the caveat. It won't handle static file errors. So if you have a route such as example.com/widgets and the user changes it to example.com/widgets.html, they will get the IIS default error page so you have to handle IIS level errors some other way.

提交回复
热议问题