Duplicate possible:
Comment puis-je gérer correctement 404 dans ASP.NET MVC?
J'ai apporté les modifications décrites dans gestionnaire d'erreurs Http 404 dans Asp.Net MVC (RC 5) et je reçois toujours la page d'erreur 404 standard. Dois-je changer quelque chose dans IIS?
Encore une autre solution.
Ajoutez ErrorControllers ou une page statique avec des informations d'erreur 404.
Modifiez votre web.config (en cas de contrôleur).
<system.web>
<customErrors mode="On" >
<error statusCode="404" redirect="~/Errors/Error404" />
</customErrors>
</system.web>
Ou en cas de page statique
<system.web>
<customErrors mode="On" >
<error statusCode="404" redirect="~/Static404.html" />
</customErrors>
</system.web>
Cela gérera les itinéraires manqués et les actions manquées.
J'ai étudié BEAUCOUP sur la façon de gérer correctement les 404 dans MVC (plus précisément MVC3), et cela, à mon humble avis est la meilleure solution que j'ai trouvée:
Dans global.asax:
public class MvcApplication : HttpApplication
{
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 404)
{
Response.Clear();
var rd = new RouteData();
rd.DataTokens["area"] = "AreaName"; // In case controller is in another area
rd.Values["controller"] = "Errors";
rd.Values["action"] = "NotFound";
IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
}
}
}
ErrorsController:
public sealed class ErrorsController : Controller
{
public ActionResult NotFound()
{
ActionResult result;
object model = Request.Url.PathAndQuery;
if (!Request.IsAjaxRequest())
result = View(model);
else
result = PartialView("_NotFound", model);
return result;
}
}
Modifier:
Si vous utilisez IoC (par exemple, AutoFac), vous devez créer votre contrôleur en utilisant:
var rc = new RequestContext(new HttpContextWrapper(Context), rd);
var c = ControllerBuilder.Current.GetControllerFactory().CreateController(rc, "Errors");
c.Execute(rc);
Au lieu de
IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
(Facultatif)
Explication:
Il y a 6 scénarios auxquels je peux penser où une application ASP.NET MVC3 peut générer des 404.
Généré par ASP.NET:
Généré par ASP.NET MVC:
Scénario 2: L'URL correspond à une route, mais spécifie un contrôleur qui n'existe pas.
Scénario 3: L'URL correspond à une route, mais spécifie une action qui n'existe pas.
Généré manuellement:
Scénario 4: Une action renvoie un HttpNotFoundResult en utilisant la méthode HttpNotFound ().
Scénario 5: Une action lève une exception HttpException avec le code d'état 404.
Scénario 6: Une action modifie manuellement la propriété Response.StatusCode sur 404.
Objectifs
(A) Afficher une page d'erreur 404 personnalisée à l'utilisateur.
(B) Conservez le code d'état 404 sur la réponse du client (particulièrement important pour le référencement).
(C) Envoyez la réponse directement, sans impliquer de redirection 302.
Tentative de solution: erreurs personnalisées
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/Errors/NotFound"/>
</customErrors>
</system.web>
Problèmes avec cette solution:
Tentative de solution: Erreurs HTTP
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
Problèmes avec cette solution:
Tentative de solution: Erreurs HTTP avec Replace
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404"/>
<error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
Problèmes avec cette solution:
Solution Essayez customErrors et les erreurs HTTP
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/Errors/NotFound"/>
</customError>
</system.web>
et
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
Problèmes avec cette solution:
Les personnes qui en avaient déjà souffert auparavant ont même essayé de créer leurs propres bibliothèques (voir http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html ). Mais la solution précédente semble couvrir tous les scénarios sans la complexité d'utiliser une bibliothèque externe.
La réponse de Marco est la meilleure solution. J'avais besoin de contrôler mon traitement des erreurs, et je veux dire vraiment le contrôler. Bien entendu, j'ai un peu étendu la solution et créé un système complet de gestion des erreurs qui gère tout. J'ai également entendu parler de cette solution dans d'autres blogs et cela semble très acceptable pour la plupart des développeurs avancés.
Voici le code final que j'utilise:
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 404)
{
var exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.Clear();
Server.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "ErrorManager";
routeData.Values["action"] = "Fire404Error";
routeData.Values["exception"] = exception;
Response.StatusCode = 500;
if (httpException != null)
{
Response.StatusCode = httpException.GetHttpCode();
switch (Response.StatusCode)
{
case 404:
routeData.Values["action"] = "Fire404Error";
break;
}
}
// Avoid IIS7 getting in the middle
Response.TrySkipIisCustomErrors = true;
IController errormanagerController = new ErrorManagerController();
HttpContextWrapper wrapper = new HttpContextWrapper(Context);
var rc = new RequestContext(wrapper, routeData);
errormanagerController.Execute(rc);
}
}
et dans mon ErrorManagerController:
public void Fire404Error(HttpException exception)
{
//you can place any other error handling code here
throw new PageNotFoundException("page or resource");
}
Maintenant, dans mon action, je lance une exception personnalisée que j'ai créée. Et mon contrôleur hérite d'une classe de contrôleur personnalisée que j'ai créée. Le contrôleur de base personnalisé a été créé pour remplacer le traitement des erreurs. Voici ma classe de contrôleur de base personnalisée:
public class MyBasePageController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
filterContext.GetType();
filterContext.ExceptionHandled = true;
this.View("ErrorManager", filterContext).ExecuteResult(this.ControllerContext);
base.OnException(filterContext);
}
}
Le "ErrorManager" dans le code ci-dessus est simplement une vue qui utilise un modèle basé sur ExceptionContext
Ma solution fonctionne parfaitement et je suis capable de gérer TOUTE erreur sur mon site Web et d’afficher différents messages en fonction de TOUT type d’exception.
On dirait que c'est le meilleur moyen de tout attraper.
Dans IIS, vous pouvez spécifier une redirection vers "certaines" pages en fonction du code d'erreur. Dans votre exemple, vous pouvez configurer 404 -> Votre page d’erreur 404 personnalisée.
Ce que je peux recommander est de regarder sur FilterAttribute. Par exemple, MVC a déjà HandleErrorAttribute. Vous pouvez le personnaliser pour ne gérer que 404. Si vous êtes intéressé, je vais regarder par exemple.
BTW
La solution (avec le dernier itinéraire) que vous avez acceptée à la question précédente ne fonctionne pas dans la plupart des situations. La deuxième solution avec HandleUnknownAction fonctionnera mais nécessitera cette modification dans chaque contrôleur ou un seul contrôleur de base.
Mon choix est une solution avec HandleUnknownAction.