How to make custom error pages work in ASP.NET MVC 4

前端 未结 11 2092
陌清茗
陌清茗 2020-11-22 12:25

I want a custom error page shown for 500, 404 and 403. Here\'s what I have done:

  1. Enabled custom errors in the web.config as follows:

    
    
            
相关标签:
11条回答
  • 2020-11-22 13:05

    Here is my solution. Use [ExportModelStateToTempData] / [ImportModelStateFromTempData] is uncomfortable in my opinion.

    ~/Views/Home/Error.cshtml:

    @{
        ViewBag.Title = "Error";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    <h2>Error</h2>
    <hr/>
    
    <div style="min-height: 400px;">
    
        @Html.ValidationMessage("Error")
    
        <br />
        <br />
    
        <button onclick="Error_goBack()" class="k-button">Go Back</button>
        <script>
            function Error_goBack() {
                window.history.back()
            }
        </script>
    
    </div>
    

    ~/Controllers/HomeController.sc:

    public class HomeController : BaseController
    {
        public ActionResult Index()
        {
            return View();
        }
    
        public ActionResult Error()
        {
            return this.View();
        }
    
        ...
    }
    

    ~/Controllers/BaseController.sc:

    public class BaseController : Controller
    {
        public BaseController() { }
    
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext.Result is ViewResult)
            {
                if (filterContext.Controller.TempData.ContainsKey("Error"))
                {
                    var modelState = filterContext.Controller.TempData["Error"] as ModelState;
                    filterContext.Controller.ViewData.ModelState.Merge(new ModelStateDictionary() { new KeyValuePair<string, ModelState>("Error", modelState) });
                    filterContext.Controller.TempData.Remove("Error");
                }
            }
            if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
            {
                if (filterContext.Controller.ViewData.ModelState.ContainsKey("Error"))
                {
                    filterContext.Controller.TempData["Error"] = filterContext.Controller.ViewData.ModelState["Error"];
                }
            }
    
            base.OnActionExecuted(filterContext);
        }
    }
    

    ~/Controllers/MyController.sc:

    public class MyController : BaseController
    {
        public ActionResult Index()
        {
            return View();
        }
    
        public ActionResult Details(int id)
        {
            if (id != 5)
            {
                ModelState.AddModelError("Error", "Specified row does not exist.");
                return RedirectToAction("Error", "Home");
            }
            else
            {
                return View("Specified row exists.");
            }
        }
    }
    

    I wish you successful projects ;-)

    0 讨论(0)
  • 2020-11-22 13:08

    I would Recommend to use Global.asax.cs File.

     protected void Application_Error(Object sender, EventArgs e)
    {
        var exception = Server.GetLastError();
        if (exception is HttpUnhandledException)
        {
            Server.Transfer("~/Error.aspx");
        }
        if (exception != null)
        {
            Server.Transfer("~/Error.aspx");
        }
        try
        {
            // This is to stop a problem where we were seeing "gibberish" in the
            // chrome and firefox browsers
            HttpApplication app = sender as HttpApplication;
            app.Response.Filter = null;
        }
        catch
        {
        }
    }
    
    0 讨论(0)
  • 2020-11-22 13:09

    There seem to be a number of steps here jumbled together. I'll put forward what I did from scratch.

    1. Create the ErrorPage controller

      public class ErrorPageController : Controller
      {
          public ActionResult Index()
          {
              return View();
          }
      
          public ActionResult Oops(int id)
          {
              Response.StatusCode = id;
              return View();
          }
      }
      
    2. Add views for these two actions (right click -> Add View). These should appear in a folder called ErrorPage.

    3. Inside App_Start open up FilterConfig.cs and comment out the error handling filter.

      public static void RegisterGlobalFilters(GlobalFilterCollection filters)
      {
          // Remove this filter because we want to handle errors ourselves via the ErrorPage controller
          //filters.Add(new HandleErrorAttribute());
      }
      
    4. Inside web.config add the following <customerErrors> entries, under System.Web

      <customErrors mode="On" defaultRedirect="~/ErrorPage/Oops">
          <error redirect="~/ErrorPage/Oops/404" statusCode="404" />
          <error redirect="~/ErrorPage/Oops/500" statusCode="500" />
      </customErrors>
      
    5. Test (of course). Throw an unhandled exception in your code and see it go to the page with id 500, and then use a URL to a page that does not exist to see 404.

    0 讨论(0)
  • 2020-11-22 13:19

    It seems i came late to the party, but you should better check this out too.

    So in system.web for caching up exceptions within the application such as return HttpNotFound()

      <system.web>
        <customErrors mode="RemoteOnly">
          <error statusCode="404" redirect="/page-not-found" />
          <error statusCode="500" redirect="/internal-server-error" />
        </customErrors>
      </system.web>
    

    and in system.webServer for catching up errors that were caught by IIS and did not made their way to the asp.net framework

     <system.webServer>
        <httpErrors errorMode="DetailedLocalOnly">
          <remove statusCode="404"/>
          <error statusCode="404" path="/page-not-found" responseMode="Redirect"/>
          <remove statusCode="500"/>
          <error statusCode="500" path="/internal-server-error" responseMode="Redirect"/>
      </system.webServer>
    

    In the last one if you worry about the client response then change the responseMode="Redirect" to responseMode="File" and serve a static html file, since this one will display a friendly page with an 200 response code.

    0 讨论(0)
  • 2020-11-22 13:20

    In web.config add this under system.webserver tag as below,

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

    and add a controller as,

    public class ErrorController : Controller
    {
        //
        // GET: /Error/
        [GET("/Error/NotFound")]
        public ActionResult NotFound()
        {
            Response.StatusCode = 404;
    
            return View();
        }
    
        [GET("/Error/ErrorPage")]
        public ActionResult ErrorPage()
        {
            Response.StatusCode = 500;
    
            return View();
        }
    }
    

    and add their respected views, this will work definitely I guess for all.

    This solution I found it from: Neptune Century

    0 讨论(0)
  • 2020-11-22 13:22

    My current setup (on MVC3, but I think it still applies) relies on having an ErrorController, so I use:

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

    And the controller contains the following:

    public class ErrorController : Controller
    {
        public ViewResult Index()
        {
            return View("Error");
        }
        public ViewResult NotFound()
        {
            Response.StatusCode = 404;  //you may want to set this to 200
            return View("NotFound");
        }
    }
    

    And the views just the way you implement them. I tend to add a bit of logic though, to show the stack trace and error information if the application is in debug mode. So Error.cshtml looks something like this:

    @model System.Web.Mvc.HandleErrorInfo
    @{
        Layout = "_Layout.cshtml";
        ViewBag.Title = "Error";
    }
    <div class="list-header clearfix">
        <span>Error</span>
    </div>
    <div class="list-sfs-holder">
        <div class="alert alert-error">
            An unexpected error has occurred. Please contact the system administrator.
        </div>
        @if (Model != null && HttpContext.Current.IsDebuggingEnabled)
        {
            <div>
                <p>
                    <b>Exception:</b> @Model.Exception.Message<br />
                    <b>Controller:</b> @Model.ControllerName<br />
                    <b>Action:</b> @Model.ActionName
                </p>
                <div style="overflow:scroll">
                    <pre>
                        @Model.Exception.StackTrace
                    </pre>
                </div>
            </div>
        }
    </div>
    
    0 讨论(0)
提交回复
热议问题