Comment faire fonctionner les pages d'erreur personnalisées ASP.NET MVC 4

je veux une page d'erreur personnalisée pour 500, 404 et 403. Voici ce que j'ai fait:

  1. permet des erreurs personnalisées dans le web.config comme suit:

    <customErrors mode="On" 
                  defaultRedirect="~/Views/Shared/Error.cshtml">
    
        <error statusCode="403" 
               redirect="~/Views/Shared/UnauthorizedAccess.cshtml" />
    
        <error statusCode="404" 
               redirect="~/Views/Shared/FileNotFound.cshtml" />
    
    </customErrors>
    
  2. enregistré HandleErrorAttribute comme un filtre d'action global dans la classe FilterConfig comme suit:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CustomHandleErrorAttribute());
        filters.Add(new AuthorizeAttribute());
    }
    
  3. a créé une page d'erreur personnalisée pour chacun des messages ci-dessus. Le par défaut, un pour 500 était déjà disponible.

  4. déclaré dans chaque erreur personnalisée Page view que le modèle pour la page est System.Web.Mvc.HandleErrorInfo

pour 500, Il affiche la page d'erreur personnalisée. Pour d'autres, non.

y a-t-il quelque chose que je manque?

il semble que ce n'est pas tout ce qu'il y a à afficher des erreurs personnalisées comme je lis à travers le code dans la méthode OnException de la classe HandleErrorAttribute et il ne manipule que 500.

Que dois-je faire pour traiter les autres erreurs?

223
demandé sur H. Pauwelyn 2012-12-17 00:23:52

11 réponses

ma configuration actuelle (sur MVC3, mais je pense qu'elle s'applique toujours) repose sur le fait d'avoir un ErrorController , donc j'utilise:

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

et le contrôleur contient ce qui suit:

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");
    }
}

et les vues juste la façon dont vous les mettez en œuvre. J'ai tendance à ajouter un peu de logique cependant, pour montrer les informations de trace et d'erreur de la pile si l'application est en mode de débogage. Donc L'Erreur.cshtml ressemble à quelque chose comme ceci:

@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>
320
répondu Pablo Romeo 2017-02-23 13:26:20

j'ai fait pablo solution et j'ai toujours eu l'erreur (MVC4)

La vue "Erreur" ou son maître n'a pas été trouvé ou pas de moteur d'affichage prend en charge la recherche de l'emplacement.

pour se débarrasser de cela, supprimer la ligne

 filters.Add(new HandleErrorAttribute());

dans FilterConfig.cs

34
répondu Machinegon 2014-04-07 18:18:51

je fais quelque chose qui nécessite moins de codage que les autres solutions affichées.

D'abord, dans ma toile.config, j'ai le suivant:

<customErrors mode="On" defaultRedirect="~/ErrorPage/Oops">
   <error redirect="~/ErrorPage/Oops/404" statusCode="404" />
   <error redirect="~/ErrorPage/Oops/500" statusCode="500" />
</customErrors>

et le controller (/Controllers/ErrorPageController.cs) contient le texte suivant:

public class ErrorPageController : Controller
{
    public ActionResult Oops(int id)
    {
        Response.StatusCode = id;

        return View();
    }
}

et enfin, la vue contient ce qui suit (dépouillé pour la simplicité, mais il peut conta:

@{ ViewBag.Title = "Oops! Error Encountered"; }

<section id="Page">
  <div class="col-xs-12 well">
    <table cellspacing="5" cellpadding="3" style="background-color:#fff;width:100%;" class="table-responsive">
      <tbody>
        <tr>
          <td valign="top" align="left" id="tableProps">
            <img width="25" height="33" src="~/Images/PageError.gif" id="pagerrorImg">
          </td>
          <td width="360" valign="middle" align="left" id="tableProps2">
            <h1 style="COLOR: black; FONT: 13pt/15pt verdana" id="errortype"><span id="errorText">@Response.Status</span></h1>
          </td>
        </tr>
        <tr>
          <td width="400" colspan="2" id="tablePropsWidth"><font style="COLOR: black; FONT: 8pt/11pt verdana">Possible causes:</font>
          </td>
        </tr>
        <tr>
          <td width="400" colspan="2" id="tablePropsWidth2">
            <font style="COLOR: black; FONT: 8pt/11pt verdana" id="LID1">
                            <hr>
                            <ul>
                                <li id="list1">
                                    <span class="infotext">
                                        <strong>Baptist explanation: </strong>There
                                        must be sin in your life. Everyone else opened it fine.<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Presbyterian explanation: </strong>It's
                                        not God's will for you to open this link.<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong> Word of Faith explanation:</strong>
                                        You lack the faith to open this link. Your negative words have prevented
                                        you from realizing this link's fulfillment.<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Charismatic explanation: </strong>Thou
                                        art loosed! Be commanded to OPEN!<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Unitarian explanation:</strong> All
                                        links are equal, so if this link doesn't work for you, feel free to
                                        experiment with other links that might bring you joy and fulfillment.<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Buddhist explanation:</strong> .........................<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Episcopalian explanation:</strong>
                                        Are you saying you have something against homosexuals?<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Christian Science explanation: </strong>There
                                        really is no link.<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Atheist explanation: </strong>The only
                                        reason you think this link exists is because you needed to invent it.<br>
                                    </span>
                                </li>
                                <li>
                                    <span class="infotext">
                                        <strong>Church counselor's explanation:</strong>
                                        And what did you feel when the link would not open?
                                    </span>
                                </li>
                            </ul>
                            <p>
                                <br>
                            </p>
                            <h2 style="font:8pt/11pt verdana; color:black" id="ietext">
                                <img width="16" height="16" align="top" src="~/Images/Search.gif">
                                HTTP @Response.StatusCode - @Response.StatusDescription <br>
                            </h2>
                        </font>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</section>

Il est tout aussi simple que cela. Il pourrait être facilement étendu pour offrir des informations d'erreur plus détaillées, mais ELMAH poignées que pour moi & le statusCode & statusDescription est tout ce dont j'ai habituellement besoin.

19
répondu coderpros 2014-11-15 11:41:44

je recommande D'utiliser Global.asax.cs Fichier.

 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
    {
    }
}
12
répondu maxspan 2014-02-11 04:47:01

il semble y avoir un certain nombre d'étapes ici mélangées. Je vais mettre en avant ce que j'ai fait à partir de zéro.

  1. créer le ErrorPage contrôleur

    public class ErrorPageController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    
        public ActionResult Oops(int id)
        {
            Response.StatusCode = id;
            return View();
        }
    }
    
  2. ajouter des vues pour ces deux actions (clic droit -> ajouter une vue). Ceux-ci doivent apparaître dans un dossier appelé ErrorPage.

  3. à l'Intérieur App_Start ouvrir FilterConfig.cs et commentez le filtre de gestion des erreurs.

    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. à l'Intérieur de web.config ajouter les entrées <customerErrors> , sous 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 (bien sûr). Lancez une exception non manipulée dans votre code et voyez-la Aller à la page avec l'id 500, puis utilisez une URL à une page qui n'existe pas pour voir 404.

8
répondu VictorySaber 2018-05-08 19:31:22

sur la base de la réponse Postée par maxspan, j'ai mis en place un projet d'échantillon minimal sur GitHub montrant toutes les pièces de travail.

en gros, nous ajoutons simplement une méthode Application_Error à global.asax.cs pour intercepter l'exception et nous donner l'occasion de rediriger (ou plus correctement, demande de transfert ) vers une page d'erreur personnalisée.

    protected void Application_Error(Object sender, EventArgs e)
    {
        // See /q/how-to-make-custom-error-pages-work-in-asp-net-mvc-4-74065/"~/Error?Message=" + exception.Message);
        }

    }
Erreur

Contrôleur:

/// <summary>
/// This controller exists to provide the error page
/// </summary>
public class ErrorController : Controller
{
    /// <summary>
    /// This action represents the error page
    /// </summary>
    /// <param name="Message">Error message to be displayed (provided via querystring parameter - a design choice)</param>
    /// <returns></returns>
    public ActionResult Index(string Message)
    {
        // We choose to use the ViewBag to communicate the error message to the view
        ViewBag.Message = Message;
        return View();
    }

}

erreur Page View:

<!DOCTYPE html>

<html>
<head>
    <title>Error</title>
</head>
<body>

    <h2>My Error</h2>
    <p>@ViewBag.Message</p>
</body>
</html>

rien d'autre n'est en cause, autre que la désactivation/suppression de filters.Add(new HandleErrorAttribute()) dans FilterConfig.cs

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //filters.Add(new HandleErrorAttribute()); // <== disable/remove
    }
}

bien que très simple à mettre en œuvre, le seul inconvénient que je vois dans cette approche est d'utiliser querystring pour fournir des informations d'exception à la page d'erreur cible.

6
répondu user3380909 2015-08-23 17:02:02

voici ma solution. Utiliser [ExportModelStateToTempData] / [ImportModelStateFromTempData] est inconfortable à mon avis.

~ / 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.");
        }
    }
}

je vous souhaite projets réussis; -)

2
répondu ADM-IT 2015-01-05 19:35:41

vous pouvez obtenir des erreurs fonctionnant correctement sans Hacker global.cs, jouer avec HandleErrorAttribute, faire la réponse.TrySkipIisCustomErrors, le branchement de Application_Error, ou quoi que ce soit:

dans le système.web (juste l'habitude, on/off)

<customErrors mode="On">
  <error redirect="/error/401" statusCode="401" />
  <error redirect="/error/500" statusCode="500" />
</customErrors>

et dans le système.webServer

<httpErrors existingResponse="PassThrough" />

maintenant les choses doivent se comporter comme prévu, et vous pouvez utiliser votre ErrorController pour afficher tout ce dont vous avez besoin.

2
répondu Robert 2015-12-14 12:45:42

j'ai tout mis en place, mais je ne pouvais toujours pas voir les pages d'erreur appropriées pour le code d'État 500 sur notre serveur de mise en scène, malgré le fait que tout fonctionnait très bien sur les serveurs de développement local.

j'ai trouvé ce billet de blog de Rick Strahl qui m'a aidé.

j'ai dû ajouter Response.TrySkipIisCustomErrors = true; à mon code de traitement des erreurs personnalisé.

0
répondu DCShannon 2015-05-08 01:57:19

il semble que je suis arrivé en retard à la fête, mais vous devriez mieux vérifier cela aussi.

system.web pour la mise en cache en place des exceptions dans l'application, comme le retour HttpNotFound()

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

et dans system.webServer pour avoir rattrapé les erreurs qui ont été relevées par L'IIS et qui ne se sont pas glissées asp.net cadre

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

dans le dernier si vous vous inquiétez de la réponse du client, puis changer le responseMode="Redirect" à responseMode="File" et servir un fichier html statique, puisque celui-ci affichera une page conviviale avec un code de réponse de 200.

0
répondu OrElse 2017-08-11 16:52:44

dans web.config ajouter ce sous système.étiquette webserver comme ci-dessous,

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

et Ajouter un contrôleur comme,

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();
    }
}

et d'ajouter leurs points de vue respectés, cela fonctionnera certainement je suppose pour tous.

Cette solution je l'ai trouvé de: Neptune siècle

0
répondu Dpk-Kumar 2017-08-30 08:06:55