Custom Error Pages with Layout

后端 未结 2 461
忘了有多久
忘了有多久 2021-01-18 18:26

I\'ve been fighting to get custom error pages to work and keep finding my way back to simply using a static page. Though the static page works, it would require remaking the

2条回答
  •  盖世英雄少女心
    2021-01-18 18:45

    I got around the same issue in my ASP.Net MVC projects by piping everything through .Net via handlers.

      
        
          
          
          
          
          
          
          
          
        
      
    

    First an ErrorController was created to handle request errors and not found requests like.

    [AllowAnonymous]
    public class ErrorController : Controller {
        // GET: Error
        public ActionResult NotFound() {
            Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
            Response.TrySkipIisCustomErrors = true;
            HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
            HttpContext.Response.TrySkipIisCustomErrors = true;
            return View();
        }
    
        public ActionResult Error() {
            Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
            Response.TrySkipIisCustomErrors = true;
            return View();
        }
    }
    

    You will notice that I call TrySkipIisCustomErrors to try to avoid IIS errors

    Then a base controller to handle all unknown actions that would map to the ErrorController.NotFound action was created.

    public abstract class FrontOfficeControllerBase : Controller {
        protected override void HandleUnknownAction(string actionName) {
            var data = ViewData;
            //Custom code to resolve the view.
            //ViewResult view = this.View(c => c.NotFound());
    
            //Manually create view with view Data
            ViewResult view = new ViewResult();
            view.ViewData = new ViewDataDictionary();
            view.ViewData["controller"] = "Error";
            view.ViewData["action"] = "NotFound";
    
            if (data != null && data.Count > 0) {
                data.ToList().ForEach(view.ViewData.Add);
            }
    
            Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
            Response.TrySkipIisCustomErrors = true;
            view.ExecuteResult(this.ControllerContext);
        }
    }
    

    All Controllers would inherit from this base controller.

    A catch all route was configured after all other routes.

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

    This made sure that if a route was not matched to any of my controllers it would safely route to the ErrorController.NotFound action.

    For the views, I created the respective NotFound.shtml and Error.cshtml paged in the Views/Shared folder and they benefited from access to the root layout, which is what I think you were looking for.

    In the end I was able to remove both the customErrors and httpErrors from web.config as there was no longer any need for them as every request was managed by the handlers and routed accordingly.

    The original idea for this structure came from this article where I mixed and matched the available options till I found a solution that worked/suited my needs.

    Exception handling in ASP.NET MVC (6 methods explained)

    Hope this helps.

提交回复
热议问题