Comment puis-je manipuler correctement 404 en ASP.NET MVC?

j'utilise RC2

utilisant le routage D'URL:

routes.MapRoute(
    "Error",
     "{*url}",
     new { controller = "Errors", action = "NotFound" }  // 404s
);

ce qui précède semble prendre en compte des requêtes comme celle-ci (en supposant des tables de route par défaut configurées par le projet initial MVC):"/blah/blah/blah / blah "

action de commande supérieure () dans le contrôleur lui-même:

// 404s - handle here (bad action requested
protected override void HandleUnknownAction(string actionName) {
    ViewData["actionName"] = actionName;
    View("NotFound").ExecuteResult(this.ControllerContext);
}  

cependant les stratégies précédentes ne traitent pas une demande à un Mauvais contrôleur / inconnu. Par exemple, je n'ai pas de "/IDoNotExist", si je le demande je reçois la page generic 404 du serveur web et pas mon 404 si j'utilise routing + override.

donc finalement, ma question Est: y a-t-il un moyen d'attraper ce type de requête en utilisant une route ou quelque chose d'autre dans le cadre MVC lui-même?

ou devrais-je utiliser Web par défaut.Config customErrors comme mon gestionnaire 404 et tout oublier? Je suppose que si je vais avec customErrors je vais devoir stocker la page 404 Générique En dehors de / vues en raison du Web.Restrictions de configuration sur l'accès direct.

417
demandé sur Flimzy 2009-03-06 21:21:39

19 réponses

le code est tiré de http://blogs.microsoft.co.il/blogs/shay/archive/2009/03/06/real-world-error-hadnling-in-asp-net-mvc-rc2.aspx et travaille en ASP.net MVC 1.0 ainsi que

Voici comment je gère les exceptions http:

protected void Application_Error(object sender, EventArgs e)
{
   Exception exception = Server.GetLastError();
   // Log the exception.

   ILogger logger = Container.Resolve<ILogger>();
   logger.Error(exception);

   Response.Clear();

   HttpException httpException = exception as HttpException;

   RouteData routeData = new RouteData();
   routeData.Values.Add("controller", "Error");

   if (httpException == null)
   {
       routeData.Values.Add("action", "Index");
   }
   else //It's an Http Exception, Let's handle it.
   {
       switch (httpException.GetHttpCode())
       {
          case 404:
              // Page not found.
              routeData.Values.Add("action", "HttpError404");
              break;
          case 500:
              // Server error.
              routeData.Values.Add("action", "HttpError500");
              break;

           // Here you can handle Views to other error codes.
           // I choose a General error template  
           default:
              routeData.Values.Add("action", "General");
              break;
      }
  }           

  // Pass exception details to the target error View.
  routeData.Values.Add("error", exception);

  // Clear the error on server.
  Server.ClearError();

  // Avoid IIS7 getting in the middle
  Response.TrySkipIisCustomErrors = true; 

  // Call target Controller and pass the routeData.
  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(    
       new HttpContextWrapper(Context), routeData));
}
253
répondu Shay Jacoby 2010-10-05 18:17:30

Exigences pour 404

voici mes exigences pour une solution 404 et ci-dessous je montre comment je l'implémente:

  • je veux gérer des itinéraires correspondant à de mauvaises actions
  • je veux gérer les routes appariées avec de mauvais contrôleurs
  • je veux gérer les routes non-assorties (urls arbitraires que mon application ne peut pas comprendre) - Je ne veux pas que ces bulles jusqu'au Global.asax ou IIS car alors Je ne peux pas rediriger correctement dans mon application MVC
  • je veux un moyen de gérer de la même manière que ci-dessus, custom 404s-like quand un ID est soumis pour un objet qui n'existe pas (peut-être supprimé)
  • je veux que tous mes 404s pour retourner une vue MVC (pas une page statique) à laquelle je peux pomper plus de données plus tard si nécessaire ( good 404 designs ) et ils doit retourner le code de statut HTTP 404

Solution

je pense que vous devriez sauver Application_Error dans le Global.asax pour les choses plus élevées,comme les exceptions et l'exploitation forestière (comme la réponse de Shay Jacoby montre) mais pas la manipulation 404. C'est pourquoi ma suggestion garde les 404 trucs en dehors du Global.fichier asax.

Étape 1: Avoir un lieu commun pour erreur 404 logique

C'est une bonne idée pour la maintenabilité. Utilisez un ErrorController de sorte que les améliorations futures à votre bien conçu page 404 peut s'adapter facilement. Aussi, assurez-vous que votre réponse a le code 404 !

public class ErrorController : MyController
{
    #region Http404

    public ActionResult Http404(string url)
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        var model = new NotFoundViewModel();
        // If the url is relative ('NotFound' route) then replace with Requested path
        model.RequestedUrl = Request.Url.OriginalString.Contains(url) & Request.Url.OriginalString != url ?
            Request.Url.OriginalString : url;
        // Dont get the user stuck in a 'retry loop' by
        // allowing the Referrer to be the same as the Request
        model.ReferrerUrl = Request.UrlReferrer != null &&
            Request.UrlReferrer.OriginalString != model.RequestedUrl ?
            Request.UrlReferrer.OriginalString : null;

        // TODO: insert ILogger here

        return View("NotFound", model);
    }
    public class NotFoundViewModel
    {
        public string RequestedUrl { get; set; }
        public string ReferrerUrl { get; set; }
    }

    #endregion
}

Étape 2: Utilisez une classe de contrôleur de base de sorte que vous pouvez facilement invoquer votre action 404 personnalisé et brancher HandleUnknownAction

404s en ASP.NET les MVC doivent: être pris à un certain nombre d'endroits. La première est HandleUnknownAction .

la méthode InvokeHttp404 crée un lieu commun pour le réacheminement vers l'action ErrorController et notre nouvelle action Http404 . Pensez sec !

public abstract class MyController : Controller
{
    #region Http404 handling

    protected override void HandleUnknownAction(string actionName)
    {
        // If controller is ErrorController dont 'nest' exceptions
        if (this.GetType() != typeof(ErrorController))
            this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<ErrorController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Error");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

    #endregion
}

Étape 3: Utilisez L'Injection de dépendance dans votre usine de contrôleur et branchez 404 HttpExceptions

comme cela (il ne doit pas être StructureMap):

MVC1.0 exemple:

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(RequestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

MVC2.0 exemple:

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == 404)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(requestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }

je pense qu'il est préférable d'attraper les erreurs plus près de leur origine. C'est pourquoi je préfère ce qui précède au handler Application_Error .

C'est le deuxième endroit pour attraper des 404s.

Étape 4: Ajouter une route NotFound à Global.asax pour les URL qui ne sont pas utilisées dans votre application

cette route devrait pointer vers notre action Http404 . Notez que le param url sera une url relative parce que le moteur de routage supprime la partie Domaine ici? C'est pourquoi nous avons toute cette logique d'url conditionnelle à L'Étape 1.

        routes.MapRoute("NotFound", "{*url}", 
            new { controller = "Error", action = "Http404" });

C'est le troisième et dernier endroit pour attraper des 404s dans une application MVC que vous n'invoquez pas vous-même. Si vous n'attrapez pas les routes non appariées ici alors MVC passera le problème jusqu'à ASP.NET (Mondial.asax) et vous ne voulez pas vraiment que dans cette situation.

Étape 5: Enfin, invoquer 404s lorsque votre application ne peut pas trouver quelque chose

comme quand une mauvaise carte D'identité est soumise à mon contrôleur de prêts (dérive de MyController ):

    //
    // GET: /Detail/ID

    public ActionResult Detail(int ID)
    {
        Loan loan = this._svc.GetLoans().WithID(ID);
        if (loan == null)
            return this.InvokeHttp404(HttpContext);
        else
            return View(loan);
    }

ce serait bien si tout cela pouvait être raccordé dans moins d'endroits avec moins de code mais je pense que cette solution est plus supportable, plus testable et assez pragmatique.

Merci pour les commentaires jusqu'à présent. J'aimerais obtenir plus.

NOTE: Cette réponse a été modifiée de façon significative par rapport à ma réponse originale, mais le but/les exigences sont les mêmes - c'est pourquoi je n'ai pas ajouté de nouvelle réponse

251
répondu Matt Kocaj 2017-05-23 10:31:35

ASP.NET MVC ne supporte pas très bien les pages 404 personnalisées. Usine de contrôleur personnalisé, route catch-all, classe de contrôleur de base avec HandleUnknownAction - argh!

IIS pages d'erreur personnalisées sont la meilleure alternative pour l'instant:

web.config

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

ErrorController

public class ErrorController : Controller
{
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        return View();
    }
}

Exemple De Projet

225
répondu Pavel Chuchuva 2015-05-04 07:28:52

Quick Answer/TL; DR

enter image description here

Pour les paresseux:

Install-Package MagicalUnicornMvcErrorToolkit -Version 1.0

puis supprimer cette ligne de global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

et ce uniquement pour IIS7+ et IIS Express.

si vous utilisez Cassini .. bien. . la messagerie unifiée .. er.. maladroit. .. awkward


Long, réponse expliquée

je sais que cela a été répondu. Mais la réponse est très SIMPLE (on applaudit David Fowler et Damian Edwards pour avoir vraiment répondu à cette question).

Il y a pas besoin de faire quelque chose de personnalisé .

Pour ASP.NET MVC3 , tous les morceaux sont là.

Step 1 -> mise à Jour de votre site web.config en DEUX endroits.

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

et

<system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404" subStatusCode="-1" />
      <error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
    </httpErrors>    

...
<system.webServer>
...
</system.web>

maintenant, notez attentivement les ROUTES que j'ai décidé d'utiliser. Vous pouvez utiliser n'importe quoi, mais mes routes sont

  • /NotFound <- pour un 404 non trouvé, page d'erreur.
  • /ServerError < - pour toute autre erreur, incluez les erreurs qui se produisent dans mon code. il s'agit d'une erreur de serveur interne de 500

voir comment la première section dans <system.web> a seulement un entrée sur les douanes? La mention statusCode="404" ? Je n'ai énuméré qu'un seul code de statut parce que toutes les autres erreurs, y compris le 500 Server Error (c.-à-d. cette erreur pénible qui se produit lorsque votre code a un bug et bloque la requête de l'utilisateur) .. toutes les autres erreurs sont gérées par le paramètre defaultRedirect="/ServerError" .. qui dit, si vous n'êtes pas une page 404 pas trouvé, alors s'il vous plaît aller à la route /ServerError .

Ok. c'est hors de la voie.. maintenant à mes routes énumérées dans global.asax

Étape 2 - Création d'itinéraires Mondiale.asax 1519260920"

Voici mon itinéraire complet..

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});

    routes.MapRoute(
        "Error - 404",
        "NotFound",
        new { controller = "Error", action = "NotFound" }
        );

    routes.MapRoute(
        "Error - 500",
        "ServerError",
        new { controller = "Error", action = "ServerError"}
        );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {controller = "Home", action = "Index", id = UrlParameter.Optional}
        );
}

qui liste deux routes ignorées - > axd's et favicons (ooo! bonus ignorer route, pour vous!) Ensuite (et L'ordre est impératif ici), j'ai mes deux routes explicites de traitement des erreurs .. suivie par tous les autres routes. Dans ce cas, l' la valeur par défaut. Bien sûr, j'en ai plus, mais c'est spécial pour mon site web. assurez-vous que les routes d'erreur sont en haut de la liste. L'ordre est impératif .

enfin, alors que nous sommes dans notre fichier global.asax , nous N'enregistrons pas globalement L'attribut HandleError. Non, non, non, monsieur. Nadda. Nope. Nien. Négatif. Noooooooooo...

supprimer cette ligne de global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

Étape 3 - Créer le contrôleur avec les méthodes d'action

maintenant .. nous ajoutons un contrôleur avec deux méthodes d'action ...

public class ErrorController : Controller
{
    public ActionResult NotFound()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    public ActionResult ServerError()
    {
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        // Todo: Pass the exception into the view model, which you can make.
        //       That's an exercise, dear reader, for -you-.
        //       In case u want to pass it to the view, if you're admin, etc.
        // if (User.IsAdmin) // <-- I just made that up :) U get the idea...
        // {
        //     var exception = Server.GetLastError();
        //     // etc..
        // }

        return View();
    }

    // Shhh .. secret test method .. ooOOooOooOOOooohhhhhhhh
    public ActionResult ThrowError()
    {
        throw new NotImplementedException("Pew ^ Pew");
    }
}

OK, voyons ça. Tout d'abord, il ya no [HandleError] attribut ici. Pourquoi? Parce que le framework intégré dans ASP.NET gère déjà les erreurs et nous avons spécifié toute la merde que nous devons faire pour gérer une erreur :) c'est dans cette méthode!

ensuite, j'ai les deux méthodes d'action. Rien de difficile. Si vous souhaitez afficher des informations d'exception, alors vous pouvez utiliser Server.GetLastError() pour obtenir ces informations.

Bonus WTF: Oui, j'ai fait une troisième méthode d'action, pour tester le traitement des erreurs.

Étape 4-Créer les vues

et enfin, créer deux vues. Mettez em dans le champ de vision normal, pour ce contrôleur.

enter image description here

Bonus commentaires

  • vous n'avez pas besoin d'un Application_Error(object sender, EventArgs e)
  • Les étapes ci-dessus tous les travaux 100% parfaitement avec Elmah . Elmah fraking wroxs!

et ça, mes amis, ça devrait être ça.

maintenant, félicitations pour avoir lu autant et avoir une licorne comme prix!

enter image description here

153
répondu Pure.Krome 2017-05-23 12:10:41

j'ai étudié beaucoup sur la façon de gérer correctement les 404s dans MVC (spécifiquement MVC3) , et ceci, IMHO est la meilleure solution que j'ai trouvé:

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

(facultatif)

explication:

AFAIK, il y a 6 cas différents où un ASP.NET les applications MVC3 peuvent générer des 404s.

(généré automatiquement par ASP.NET Framework:)

(1) une URL ne trouve pas de correspondance dans la table des routes.

(généré automatiquement par ASP.NET MVC Framework:)

(2) une URL trouve une correspondance dans la table de route, mais spécifie un contrôleur inexistant.

(3) une URL trouve une correspondance dans la table de route, mais spécifie une action non-existante.

(généré manuellement:)

(4) une action renvoie un résultat Httpnotfound en utilisant la méthode HttpNotFound ().

(5) une action lance une HttpException avec le code d'état 404.

(6) une action modifie manuellement la réponse.StatusCode propriété à 404.

normalement, vous voulez accomplir 3 objectifs:

(1) afficher une page d'erreur 404 personnalisée à l'utilisateur.

(2) maintenir le code d'état 404 sur la réponse du client (particulièrement important pour le SEO).

(3) envoyer la réponse directement, sans impliquer une redirection 302.

il y a plusieurs façons d'y parvenir:

(1)

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

problèmes avec cette solution:

  1. N'est pas conforme à l'objectif (1) dans les cas (1), (4), (6).
  2. Ne répond pas automatiquement à l'objectif 2. Il doit être programmé manuellement.
  3. N'est pas conforme à l'objectif (3).

(2)

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

  1. fonctionne uniquement sur IIS 7+.
  2. N'est pas conforme à l'objectif (1) dans les cas (2), (3), (5).
  3. Ne répond pas automatiquement à l'objectif 2. Il doit être programmé manuellement.

(3)

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

  1. fonctionne uniquement sur IIS 7+.
  2. ne répond pas automatiquement à l'objectif 2. Il doit être programmé manuellement.
  3. il obscurcit le niveau d'application http exception. Par exemple: Je ne peux pas utiliser la section customErrors, système.Web.Mvc.HandleErrorAttribute, etc. Il ne peut pas seulement afficher des pages d'erreur génériques.

(4)

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

  1. fonctionne uniquement sur IIS 7+.
  2. ne répond pas automatiquement à l'objectif 2. Il doit être programmé manuellement.
  3. N'est pas conforme à l'objectif (3) dans les cas (2), (3), (5).

les gens qui ont eu des problèmes avec cela avant 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 cas sans la complexité de l'utilisation d'une bibliothèque externe.

82
répondu Marco 2012-05-22 22:29:22

j'aime vraiment cottsaks solution et pense que son très clairement expliqué. mon seul ajout a été de modifier l'étape 2 comme suit:

public abstract class MyController : Controller
{

    #region Http404 handling

    protected override void HandleUnknownAction(string actionName)
    {
        //if controller is ErrorController dont 'nest' exceptions
        if(this.GetType() != typeof(ErrorController))
        this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<ErrorController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Error");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

    #endregion
}

essentiellement ceci empêche les urls contenant des actions invalides et les controllers de déclencher la routine d'exception deux fois. eg pour les urls telles que asdfsdf / dfgdfgd

13
répondu Dave Lowe 2010-11-01 06:16:22

la seule façon d'obtenir la méthode de travail de @cottsak pour les contrôleurs invalides était de modifier la demande de route existante dans CustomControllerFactory, comme suit:

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType); 
            else
                return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
            {
                requestContext.RouteData.Values["controller"] = "Error";
                requestContext.RouteData.Values["action"] = "Http404";
                requestContext.RouteData.Values.Add("url", requestContext.HttpContext.Request.Url.OriginalString);

                return ObjectFactory.GetInstance<ErrorController>();
            }
            else
                throw ex;
        }
    }
}

je dois mentionner que j'utilise MVC 2.0.

6
répondu Dave K 2010-07-29 23:43:14

Voici une autre méthode utilisant les outils MVC que vous pouvez gérer les requêtes vers les noms de mauvais controller, les noms de mauvaise route, et tout autre critère que vous jugez approprié à l'intérieur d'une méthode D'Action. Personnellement, je préfère éviter autant de web.les paramètres de configuration comme possible, parce qu'ils font la redirection 302 / 200 et ne prennent pas en charge la réponse Write ( Server.Transfer ) en utilisant des vues de rasoir. Je préfère retourner un 404 avec une page d'erreur personnalisée pour des raisons de référencement.

une partie de ceci est une nouvelle prise en charge la technique de cottsak ci-dessus.

cette solution utilise également le web minimal.paramètres de configuration favorisant les filtres D'erreur MVC 3 à la place.

Utilisation

il suffit de lancer une HttpException à partir d'une action ou d'une action personnalisée ActionFilterAttribute.

Throw New HttpException(HttpStatusCode.NotFound, "[Custom Exception Message Here]")

Étape 1

ajouter le paramètre suivant à votre site web.config. Ceci est nécessaire pour utiliser HandleErrorAttribute de MVC.

<customErrors mode="On" redirectMode="ResponseRedirect" />

l'Étape 2

Ajouter un HandleHttpErrorAttribute personnalisé similaire à HandleErrorAttribute du cadre MVC, sauf pour les erreurs HTTP:

<AttributeUsage(AttributeTargets.All, AllowMultiple:=True)>
Public Class HandleHttpErrorAttribute
    Inherits FilterAttribute
    Implements IExceptionFilter

    Private Const m_DefaultViewFormat As String = "ErrorHttp{0}"

    Private m_HttpCode As HttpStatusCode
    Private m_Master As String
    Private m_View As String

    Public Property HttpCode As HttpStatusCode
        Get
            If m_HttpCode = 0 Then
                Return HttpStatusCode.NotFound
            End If
            Return m_HttpCode
        End Get
        Set(value As HttpStatusCode)
            m_HttpCode = value
        End Set
    End Property

    Public Property Master As String
        Get
            Return If(m_Master, String.Empty)
        End Get
        Set(value As String)
            m_Master = value
        End Set
    End Property

    Public Property View As String
        Get
            If String.IsNullOrEmpty(m_View) Then
                Return String.Format(m_DefaultViewFormat, Me.HttpCode)
            End If
            Return m_View
        End Get
        Set(value As String)
            m_View = value
        End Set
    End Property

    Public Sub OnException(filterContext As System.Web.Mvc.ExceptionContext) Implements System.Web.Mvc.IExceptionFilter.OnException
        If filterContext Is Nothing Then Throw New ArgumentException("filterContext")

        If filterContext.IsChildAction Then
            Return
        End If

        If filterContext.ExceptionHandled OrElse Not filterContext.HttpContext.IsCustomErrorEnabled Then
            Return
        End If

        Dim ex As HttpException = TryCast(filterContext.Exception, HttpException)
        If ex Is Nothing OrElse ex.GetHttpCode = HttpStatusCode.InternalServerError Then
            Return
        End If

        If ex.GetHttpCode <> Me.HttpCode Then
            Return
        End If

        Dim controllerName As String = filterContext.RouteData.Values("controller")
        Dim actionName As String = filterContext.RouteData.Values("action")
        Dim model As New HandleErrorInfo(filterContext.Exception, controllerName, actionName)

        filterContext.Result = New ViewResult With {
            .ViewName = Me.View,
            .MasterName = Me.Master,
            .ViewData = New ViewDataDictionary(Of HandleErrorInfo)(model),
            .TempData = filterContext.Controller.TempData
        }
        filterContext.ExceptionHandled = True
        filterContext.HttpContext.Response.Clear()
        filterContext.HttpContext.Response.StatusCode = Me.HttpCode
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = True
    End Sub
End Class

l'Étape 3

ajouter des filtres à la collection Globalfilter ( GlobalFilters.Filters ) dans Global.asax . Cet exemple acheminera toutes les erreurs Internalserverror (500) vers la vue partagée des erreurs ( Views/Shared/Error.vbhtml ). Les erreurs NotFound (404) seront envoyées à ErrorHttp404.vbhtml dans le partagé leur point de vue. J'ai ajouté une erreur 401 ici pour vous montrer comment cela peut être étendu pour des codes D'erreur HTTP supplémentaires. Notez que ces vues doivent être partagées, et qu'elles utilisent toutes l'objet System.Web.Mvc.HandleErrorInfo comme modèle.

filters.Add(New HandleHttpErrorAttribute With {.View = "ErrorHttp401", .HttpCode = HttpStatusCode.Unauthorized})
filters.Add(New HandleHttpErrorAttribute With {.View = "ErrorHttp404", .HttpCode = HttpStatusCode.NotFound})
filters.Add(New HandleErrorAttribute With {.View = "Error"})

Étape 4

créez une classe de contrôleur de base et héritez-en dans vos contrôleurs. Cette étape nous permet de gérer les noms d'actions inconnus et d'augmenter L'erreur HTTP 404 à notre HandleHttpErrorAttribute.

Public Class BaseController
    Inherits System.Web.Mvc.Controller

    Protected Overrides Sub HandleUnknownAction(actionName As String)
        Me.ActionInvoker.InvokeAction(Me.ControllerContext, "Unknown")
    End Sub

    Public Function Unknown() As ActionResult
        Throw New HttpException(HttpStatusCode.NotFound, "The specified controller or action does not exist.")
        Return New EmptyResult
    End Function
End Class

Étape 5

créez un contrôleur d'accès au répertoire, et le surchargez dans votre Global.fichier asax dans Application_Start. Cette étape nous permet d'augmenter L'exception HTTP 404 lorsqu'un nom de contrôleur invalide a été spécifié.

Public Class MyControllerFactory
    Inherits DefaultControllerFactory

    Protected Overrides Function GetControllerInstance(requestContext As System.Web.Routing.RequestContext, controllerType As System.Type) As System.Web.Mvc.IController
        Try
            Return MyBase.GetControllerInstance(requestContext, controllerType)
        Catch ex As HttpException
            Return DependencyResolver.Current.GetService(Of BaseController)()
        End Try
    End Function
End Class

'In Global.asax.vb Application_Start:

controllerBuilder.Current.SetControllerFactory(New MyControllerFactory)

Étape 6

incluez un itinéraire spécial dans votre RoutTable.Les Routes pour L'action inconnue de BaseController. Cela nous aidera à augmenter un 404 dans le cas où un utilisateur accède à une commande inconnue, ou inconnu.

'BaseController
routes.MapRoute( _
    "Unknown", "BaseController/{action}/{id}", _
    New With {.controller = "BaseController", .action = "Unknown", .id = UrlParameter.Optional} _
)

résumé

cet exemple a démontré comment on peut utiliser le framework MVC pour retourner les Codes D'erreur Http 404 au navigateur sans redirection en utilisant les attributs de filtre et les vues d'erreur partagées. Il affiche également la même page d'erreur personnalisée lorsque des noms de controller et des noms d'action invalides sont spécifiés.

je vais ajouter une capture d'écran d'un invalide nom du contrôleur, nom de l'action, et un 404 personnalisé soulevé de L'action Home/TriggerNotFound si j'obtiens assez de votes pour poster un =). Fiddler renvoie un message 404 lorsque j'accède aux URLs suivantes en utilisant cette solution:

/InvalidController
/Home/InvalidRoute
/InvalidController/InvalidRoute
/Home/TriggerNotFound

cottsak du post ci-dessus et ces articles sont de bonnes références.

4
répondu sky-dev 2017-04-12 07:31:25

ma solution raccourcie qui fonctionne avec les zones non encombrées, les contrôleurs et les actions:

  1. créez une vue 404.cshtml.

  2. créez une classe de base pour vos contrôleurs:

    public class Controller : System.Web.Mvc.Controller
    {
        protected override void HandleUnknownAction(string actionName)
        {
            Http404().ExecuteResult(ControllerContext);
        }
    
        protected virtual ViewResult Http404()
        {
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            return View("404");
        }
    }
    
  3. créer une usine de contrôleur personnalisé retournant votre contrôleur de base comme un repli:

    public class ControllerFactory : DefaultControllerFactory
    {
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType != null)
                return base.GetControllerInstance(requestContext, controllerType);
    
            return new Controller();
        }
    }
    
  4. ajouter à Application_Start() la ligne suivante:

    ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
    
4
répondu Herman Kan 2014-05-23 13:09:51

dans MVC4 WebAPI 404 peut être manipulé de la manière suivante,

COURS APICONTROLLER

    // GET /api/courses/5
    public HttpResponseMessage<Courses> Get(int id)
    {
        HttpResponseMessage<Courses> resp = null;

        var aCourse = _courses.Where(c => c.Id == id).FirstOrDefault();

        resp = aCourse == null ? new HttpResponseMessage<Courses>(System.Net.HttpStatusCode.NotFound) : new HttpResponseMessage<Courses>(aCourse);

        return resp;
    }

HOME CONTROLLER

public ActionResult Course(int id)
{
    return View(id);
}

VIEW

<div id="course"></div>
<script type="text/javascript">
    var id = @Model;
    var course = $('#course');
    $.ajax({    
        url: '/api/courses/' + id,
        success: function (data) {
            course.text(data.Name);
        },
        statusCode: {
            404: function() 
            {
                course.text('Course not available!');    
            }
        }
    });
</script>

GLOBAL

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

résultats

enter image description here

3
répondu Diganta Kumar 2012-05-08 12:59:48

Try NotFoundMVC on nuget. Ça marche, pas d'installation.

2
répondu DarthVader 2013-07-09 14:06:53

ma solution, au cas où quelqu'un la trouve utile.

Dans Web.config:

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

Dans Controllers/ErrorController.cs :

public class ErrorController : Controller
{
    public ActionResult PageNotFound()
    {
        if(Request.IsAjaxRequest()) {
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            return Content("Not Found", "text/plain");
        }

        return View();
    }
}

ajoute un PageNotFound.cshtml dans le dossier Shared , et c'est tout.

2
répondu Konamiman 2013-10-01 10:31:13

il me semble que la norme CustomErrors configuration devrait seulement fonctionner cependant, en raison de la dépendance sur Server.Transfer il semble que la mise en œuvre interne de ResponseRewrite n'est pas compatible avec MVC.

cela ressemble à un trou de fonctionnalité flagrant pour moi, donc j'ai décidé de ré-implémenter cette fonctionnalité en utilisant un module HTTP. La solution ci-dessous vous permet de gérer n'importe quel code D'état HTTP (y compris 404) en redirigeant vers n'importe quel code valide MVC route comme vous le feriez normalement.

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="404.aspx" />
    <error statusCode="500" redirect="~/MVCErrorPage" />
</customErrors>

ceci a été testé sur les plates-formes suivantes;

  • MVC4 en mode Pipeline intégré (IIS Express 8)
  • MVC4 en Mode Classique (VS Development Server, Cassini)
  • MVC4 en Mode Classique (IIS6)

prestations

  • Générique solution qui peut être intégrée à n'importe quel projet MVC
  • permet de prendre en charge la configuration traditionnelle des erreurs
  • fonctionne à la fois en mode Pipeline intégré et en mode Classique

La Solution

namespace Foo.Bar.Modules {

    /// <summary>
    /// Enables support for CustomErrors ResponseRewrite mode in MVC.
    /// </summary>
    public class ErrorHandler : IHttpModule {

        private HttpContext HttpContext { get { return HttpContext.Current; } }
        private CustomErrorsSection CustomErrors { get; set; }

        public void Init(HttpApplication application) {
            System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
            CustomErrors = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");

            application.EndRequest += Application_EndRequest;
        }

        protected void Application_EndRequest(object sender, EventArgs e) {

            // only handle rewrite mode, ignore redirect configuration (if it ain't broke don't re-implement it)
            if (CustomErrors.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite && HttpContext.IsCustomErrorEnabled) {

                int statusCode = HttpContext.Response.StatusCode;

                // if this request has thrown an exception then find the real status code
                Exception exception = HttpContext.Error;
                if (exception != null) {
                    // set default error status code for application exceptions
                    statusCode = (int)HttpStatusCode.InternalServerError;
                }

                HttpException httpException = exception as HttpException;
                if (httpException != null) {
                    statusCode = httpException.GetHttpCode();
                }

                if ((HttpStatusCode)statusCode != HttpStatusCode.OK) {

                    Dictionary<int, string> errorPaths = new Dictionary<int, string>();

                    foreach (CustomError error in CustomErrors.Errors) {
                        errorPaths.Add(error.StatusCode, error.Redirect);
                    }

                    // find a custom error path for this status code
                    if (errorPaths.Keys.Contains(statusCode)) {
                        string url = errorPaths[statusCode];

                        // avoid circular redirects
                        if (!HttpContext.Request.Url.AbsolutePath.Equals(VirtualPathUtility.ToAbsolute(url))) {

                            HttpContext.Response.Clear();
                            HttpContext.Response.TrySkipIisCustomErrors = true;

                            HttpContext.Server.ClearError();

                            // do the redirect here
                            if (HttpRuntime.UsingIntegratedPipeline) {
                                HttpContext.Server.TransferRequest(url, true);
                            }
                            else {
                                HttpContext.RewritePath(url, false);

                                IHttpHandler httpHandler = new MvcHttpHandler();
                                httpHandler.ProcessRequest(HttpContext);
                            }

                            // return the original status code to the client
                            // (this won't work in integrated pipleline mode)
                            HttpContext.Response.StatusCode = statusCode;

                        }
                    }

                }

            }

        }

        public void Dispose() {

        }


    }

}

Utilisation

incluez ceci comme dernier module HTTP dans votre web.config

  <system.web>
    <httpModules>
      <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
    </httpModules>
  </system.web>

  <!-- IIS7+ -->
  <system.webServer>
    <modules>
      <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
    </modules>
  </system.webServer>

pour ceux d'entre vous qui font attention, vous remarquerez qu'en mode Pipeline intégré cela répondra toujours avec HTTP 200 en raison de la façon dont Server.TransferRequest fonctionne. Pour retourner le code d'erreur approprié, j'utilise le contrôleur d'erreur suivant.

public class ErrorController : Controller {

    public ErrorController() { }

    public ActionResult Index(int id) {
        // pass real error code to client
        HttpContext.Response.StatusCode = id;
        HttpContext.Response.TrySkipIisCustomErrors = true;

        return View("Errors/" + id.ToString());
    }

}
2
répondu Red Taz 2015-03-31 15:39:03

concernant les erreurs dans ASP.NET MVC est juste un emmerdeur. J'ai essayé beaucoup de suggestions sur cette page et sur d'autres questions et sites et rien ne fonctionne bien. Une suggestion a été de traiter les erreurs sur web.config à l'intérieur du système.webserver mais que juste renvoie des pages vierges .

mon but lorsque j'ai trouvé cette solution était de;

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

voici ma solution.

1 .Ajouter ce qui suit au système .web de la section

   <system.web>
     <customErrors mode="On" redirectMode="ResponseRewrite">
      <error statusCode="404"  redirect="~/Error/404.aspx" />
      <error statusCode="500" redirect="~/Error/500.aspx" />
     </customErrors>
    <system.web>

ce qui précède gère toutes les URL qui ne sont pas gérées par les routes .config et unhandled exceptions, en particulier celles rencontrées sur les vues. Avis I utilisé aspx pas html . C'est pour que je puisse ajouter un code de réponse sur le code derrière.

2 . Créez un dossier appelé erreur (ou ce que vous préférez) à la racine de votre projet et ajoutez les deux formulaires Web. Ci-dessous est ma page 404;

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title >Page Not found</title>
    <link href="<%=ResolveUrl("~/Content/myapp.css")%>" rel="stylesheet" />
</head>
<body>
    <div class="top-nav">
      <a runat="server" class="company-logo" href="~/"></a>
    </div>
    <div>
        <h1>404 - Page Not found</h1>
        <p>The page you are looking for cannot be found.</p>
        <hr />
        <footer></footer>
    </div>
</body>
</html>

et sur le code derrière J'ai mis le code de réponse

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

Faire de même pour les 500 page

3 .Pour gérer les erreurs au sein des contrôleurs. Il y a beaucoup de façons de le faire. C'est ce qui a fonctionné pour moi. Tous mes contrôleurs héritent d'un contrôleur de base. Dans le contrôleur de base, j'ai les méthodes suivantes

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 .Ajouter le CustomError.cshtml à votre partagé dossier vues. Ci-dessous est la mienne;

<h1>@ViewBag.Title</h1>
<br />
<p>@ViewBag.Message</p>

maintenant dans votre contrôleur d'application vous pouvez faire quelque chose comme ça;

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

Maintenant, pour la mise en garde . Il ne gère pas les erreurs de fichiers statiques. Donc si vous avez une route telle que example.com/widgets et l'utilisateur le modifie en example.com/widgets.html , ils obtiendront la page d'erreur par défaut IIS donc vous devez gérer le niveau IIS les erreurs d'une autre façon.

2
répondu Moses Machua 2016-09-01 12:08:24

affichant une réponse depuis mon commentaire était trop long...

C'est à la fois un commentaire et des questions à la licorne post / réponse:

https://stackoverflow.com/a/7499406/687549

je préfère cette réponse plutôt que les autres pour sa simplicité et le fait qu'apparemment certains gens de Microsoft ont été consultés. J'ai trois questions cependant et si elles peuvent être répondues alors je vais appeler cette réponse le saint graal de tous les 404/500 erreur réponses sur les interwebs pour un ASP.NET MVC (x) app.

@Pure.Krome

  1. pouvez - vous mettre à jour votre réponse avec les éléments de SEO à partir des commentaires signalés par GWB (il n'y a jamais eu aucune mention de cela dans votre réponse) - <customErrors mode="On" redirectMode="ResponseRewrite"> et <httpErrors errorMode="Custom" existingResponse="Replace"> ?

  2. pouvez-vous demander à votre ASP.NET l'équipe des amis si c'est d'accord de le faire comme ça - serait agréable de avoir une certaine confirmation - peut-être que c'est un grand non-non pour changer redirectMode et existingResponse de cette façon pour être en mesure de jouer bien avec SEO?!

  3. pouvez-vous ajouter un peu de clarification autour de tous ces trucs ( customErrors redirectMode="ResponseRewrite" , customErrors redirectMode="ResponseRedirect" , httpErrors errorMode="Custom" existingResponse="Replace" , supprimer customErrors complètement comme quelqu'un l'a suggéré) après avoir parlé à vos amis chez Microsoft?

comme je le disais; ce serait la supernice si nous pourrait rendre votre réponse plus complète car cela semble être une question assez populaire avec 54 000+ points de vue.

mise à Jour : Licorne réponse est un 302 Found et un 200 OK et ne peut pas être modifié pour ne revenir 404 à l'aide d'un itinéraire. Il doit s'agir d'un fichier physique qui n'est pas très MVC:ish. Alors passons à une autre solution. Dommage car cela semblait être l'ultime MVC:ish réponse à ce jour.

1
répondu PussInBoots 2017-05-23 11:47:28

ajoutant ma solution, qui est presque identique à Herman Kan, avec une petite ride pour lui permettre de travailler pour mon projet.

créer un contrôleur d'erreur personnalisé:

public class Error404Controller : BaseController
{
    [HttpGet]
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        return View("404");
    }
}

puis créer une usine de contrôleur personnalisé:

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return controllerType == null ? new Error404Controller() : base.GetControllerInstance(requestContext, controllerType);
    }
}

enfin, ajouter un contrôleur d'erreur personnalisé:

protected override void HandleUnknownAction(string actionName)
{
    var errorRoute = new RouteData();
    errorRoute.Values.Add("controller", "Error404");
    errorRoute.Values.Add("action", "PageNotFound");
    new Error404Controller().Execute(new RequestContext(HttpContext, errorRoute));
}

Et c'est tout. Pas besoin pour le Web.changements de configuration.

1
répondu Rob Lyndon 2017-02-03 12:44:39

1) Créer la classe contrôleur abstrait.

public abstract class MyController:Controller
{
    public ActionResult NotFound()
    {
        Response.StatusCode = 404;
        return View("NotFound");
    }

    protected override void HandleUnknownAction(string actionName)
    {
        this.ActionInvoker.InvokeAction(this.ControllerContext, "NotFound");
    }
    protected override void OnAuthorization(AuthorizationContext filterContext) { }
}  

2 )Faites l'héritage de cette classe abstraite dans vos tous les contrôleurs

public class HomeController : MyController
{}  

3) et ajouter une vue nommée "NotFound" dans votre dossier View-Shared.

1
répondu Mehmet 2017-02-20 13:21:06

j'ai parcouru la plupart des solutions postées sur ce fil. Bien que cette question soit peut-être ancienne, elle est encore très applicable aux nouveaux projets, même maintenant.j'ai donc passé beaucoup de temps à lire les réponses présentées ici et ailleurs.

comme @Marco a souligné les différents cas dans lesquels un 404 peut se produire, j'ai vérifié la solution que j'ai compilé ensemble par rapport à cette liste. En plus de sa liste d'exigences, j'en ai ajouté une autre.

  • la solution devrait être capable de traiter les appels MVC ainsi que les appels AJAX/WebAPI de la manière la plus appropriée. (i.e. si 404 se produit dans MVC, il devrait montrer la page non trouvée et si 404 se produit dans WebAPI, il ne devrait pas détourner la réponse XML/JSON de sorte que la consommation Javascript peut le parser facilement).

cette solution est 2 fois:

Première partie provient de la @Guillaume à https://stackoverflow.com/a/27354140/2310818 . Leur solution prend en charge tout 404 causé par une route non valide, un contrôleur non valide et une action non valide.

l'idée est de créer un formulaire Web et de le faire appeler l'action NotFound de votre contrôleur D'erreurs MVC. Il fait tout cela sans aucune redirection de sorte que vous ne verrez pas un seul 302 Dans Fiddler. L'URL d'origine est également préservée, ce qui rend cette solution fantastique!


la deuxième partie vient de @Germán à https://stackoverflow.com/a/5536676/2310818 . Leur solution prend en charge tout 404 retourné par vos actions sous la forme de HttpNotFoundResult() ou de throw new HttpException()!

l'idée est de faire examiner par un filtre la réponse ainsi que l'exception lancée par vos contrôleurs MVC et d'appeler l'action appropriée dans votre contrôleur des erreurs. Encore cette solution fonctionne sans aucune redirection et l'url d'origine est préservé!


comme vous pouvez le voir, ces deux solutions combinées offrent un mécanisme de traitement des erreurs très robuste et ils répondent à toutes les exigences énumérées par @Marco ainsi que mes exigences. Si vous souhaitez voir un exemple de travail ou une démonstration de cette solution, merci de laisser dans les commentaires et je serais heureux de les mettre ensemble.

0
répondu Parth Shah 2017-05-23 11:54:58

j'ai parcouru tous les articles mais rien ne fonctionne pour moi: Mon type d'utilisateur d'exigence n'importe quoi dans votre page d'url personnalisé 404 devrait montrer.J'ai pensé qu'il est très simple.Mais vous devez comprendre la manipulation de 404 correctement:

 <system.web>
    <customErrors mode="On" redirectMode="ResponseRewrite">
      <error statusCode="404" redirect="~/PageNotFound.aspx"/>
    </customErrors>
  </system.web>
<system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404"/>
      <error statusCode="404" path="/PageNotFound.html" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

j'ai trouvé cet article très utile.doit être lu à la fois. Custome page d'erreur-Ben Foster

0
répondu Thakur Rock 2015-07-30 06:23:55