Routing per la pagina di errore 404 di ASP.NET MVC personalizzata


116

Sto cercando di creare una pagina di errore HTTP 404 personalizzata quando qualcuno digita un URL che non richiama un'azione o un controller valido in ASP.NET MVC, invece di visualizzare l'errore ASP.NET generico "Risorsa non trovata".

Non voglio usare web.config per gestire questo.

C'è qualche tipo di magia di instradamento che posso fare per rilevare URL non validi?

Aggiornamento: ho provato la risposta data, tuttavia ricevo ancora il brutto messaggio "Risorsa non trovata".

Un altro aggiornamento: Ok, a quanto pare qualcosa è cambiato in RC1. Ho anche provato specificamente a intercettare 404 su un HttpExceptione ancora mi dà solo la pagina "Risorsa non trovata".

Ho anche usato la funzionalità delle risorse di MvcContrib e niente - lo stesso problema. Qualche idea?



@Peter Questa è una soluzione che ho aggiunto che oltre a sovrascrivere la HandleUnknownAction per mostrare una pagina non trovata vista quando un'azione non esiste e quindi il gestore degli errori personalizzato ASP.net integrato per gestire qualsiasi altra cosa traballante che gli utenti possono digitare .
dswatik


8
Odio quando altri utenti sono presuntuosi e dicono cose come "perché dovresti farlo? Fallo e basta ..." Ma suggerirei che se non c'è nulla che ti impedisca di utilizzare l'approccio web.config e soddisfa le tue esigenze, è un approccio standard ed elegante. Qualsiasi feedback su questo approccio è apprezzato, in quanto potrebbero esserci dei problemi che non conosco.
Sean

Risposte:


10

Aggiungi semplicemente cattura tutte le rotte alla fine della tabella delle rotte e visualizza la pagina che desideri con essa.

Vedere: Come posso fare un catch all route per gestire le query "404 page not found" per ASP.NET MVC?


Ho provato questo, tuttavia, ricevo ancora il brutto messaggio di risorsa non trovata predefinito di ASP.NET ..
dswatik

3
Non trovo una soluzione definitiva (e flessibile !!) a questo problema né in questa risposta né nel link fornito.
Peter

4
Nemmeno io ... questa sembra una specie di risposta hacky. Sto cercando più un modo per far sì che customErrors si comporti come fanno in WebForms. Qualche idea?
JC Grubbs

1
Entrambi non funzionano e in linea di principio è un male. Non funziona perché non rileva gli URL non validi che corrispondono a uno dei modelli di routing precedenti. Cattivo in linea di principio perché converte ciò che dovrebbe essere un errore in non un errore. Il reindirizzamento a una pagina denominata "Errore" è diverso dal reindirizzamento a una pagina di errore. Vuoi mantenerlo come un errore, registrare l'errore, quindi gestirlo come un errore. Gli errori sono informazioni preziose.
Matteo

105

Ho provato ad abilitare errori personalizzati sul server di produzione per 3 ore, sembra che abbia trovato la soluzione finale come farlo in ASP.NET MVC senza percorsi.

Per abilitare gli errori personalizzati nell'applicazione ASP.NET MVC abbiamo bisogno di (IIS 7+):

  1. Configura pagine personalizzate in configurazione web nella system.websezione:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>

    RemoteOnlysignifica che sulla rete locale vedrai errori reali (molto utili durante lo sviluppo). Possiamo anche riscrivere la pagina di errore per qualsiasi codice di errore.

  2. Imposta il parametro Magic Response e il codice di stato della risposta (nel modulo di gestione degli errori o nell'attributo dell'handle di errore)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
  3. Imposta un'altra impostazione magica nella configurazione web nella system.webServersezione:

    <httpErrors errorMode="Detailed" />

Questa è stata l'ultima cosa che ho trovato e dopo posso vedere gli errori personalizzati sul server di produzione.


8
Questa non è ancora una soluzione ideale. Non ti fornisce i codici di risposta HTTP corretti. Utilizzo dei customErrorsrisultati in un reindirizzamento 302 solo per caricare la pagina di errore.
Justin Helgerson

@ Ek0nomik non ho mai visto soluzioni ideali :)
Andrew Orsich

2
@JustinHelgerson Ho impostato un ErrorController per ogni codice di stato e ho impostato i codici di risposta all'interno di quelle azioni e imposta i codici di risposta bene .. Ho provato con Fiddler e i codici di stato 404 rispondono con un 404 e le pagine con 500 errori rispondono con un 500. E in entrambi i casi le mie visualizzazioni personalizzate degli errori vengono fornite
Shane Neuville

il mio compagno di squadra ha appena eliminato la visualizzazione degli errori nella cartella condivisa , per rendere l'errore di runtime con codice di stato 500 per reindirizzare alla pagina di errore personalizzata come menzionato qui e qui . La speranza aiuta qualcuno.
shaijut

41

Ho fatto funzionare la mia gestione degli errori creando un ErrorController che restituisce le visualizzazioni in questo articolo. Ho anche dovuto aggiungere "Catch All" al percorso in global.asax.

Non riesco a vedere come arriverà a nessuna di queste pagine di errore se non è in Web.config ..? Il mio Web.config doveva specificare:

customErrors mode="On" defaultRedirect="~/Error/Unknown"

e poi ho anche aggiunto:

error statusCode="404" redirect="~/Error/NotFound"

2
Grazie - questo mi ha aiutato, 2 anni dopo! Cosa fai se desideri solo un errore personalizzato per 404, nient'altro?
Shaul Behr

1
@ Shaul un altro anno dopo ... non impostare defaultRedirect, escludi del tutto l'attributo.
NJE

27

fonte

NotFoundMVC : fornisce una pagina 404 intuitiva ogni volta che un controller, un'azione o una route non viene trovata nell'applicazione ASP.NET MVC3. Viene eseguito il rendering di una visualizzazione denominata NotFound invece della pagina di errore ASP.NET predefinita.

Puoi aggiungere questo plugin tramite nuget usando: Install-Package NotFoundMvc

NotFoundMvc si installa automaticamente durante l'avvio dell'applicazione web. Gestisce tutti i diversi modi in cui una 404 HttpException viene solitamente generata da ASP.NET MVC. Ciò include un controller, un'azione e un percorso mancanti.

Guida all'installazione passo passo:

1 - Fare clic con il pulsante destro del mouse sul progetto e selezionare Gestisci pacchetti Nuget ...

2 - Cerca NotFoundMvce installalo. inserisci qui la descrizione dell'immagine

3 - Una volta completata l'installazione, due file verranno aggiunti al progetto. Come mostrato negli screenshot qui sotto.

inserisci qui la descrizione dell'immagine

4 - Apri il NotFound.cshtml appena aggiunto presente in Views / Shared e modificalo a tuo piacimento. Ora esegui l'applicazione e digita un URL errato e sarai accolto con una pagina 404 user friendly.

inserisci qui la descrizione dell'immagine

Non più, gli utenti riceveranno messaggi di errore come Server Error in '/' Application. The resource cannot be found.

Spero che questo ti aiuti :)

PS: Complimenti ad Andrew Davey per aver creato un plugin così fantastico.


@niico Dall'analisi del codice sorgente sembra impostare il codice di risposta su 404, quindi sì.
Will Dean il

20

Prova questo in web.config per sostituire le pagine di errore di IIS. Questa è la soluzione migliore immagino e invia anche il codice di stato corretto.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

Altre informazioni da Tipila - Usa pagine di errore personalizzate ASP.NET MVC


1
+1. Questa è l'unica cosa che sembrava funzionare in modo coerente per me su MVC5 con più aree.
hawkke

Questa è la soluzione più semplice. Tuttavia, non puoi usare la sintassi del rasoio nella tua pagina di errore.
highace

15

Questa soluzione non necessita di modifiche al file web.config o di percorsi catch-all.

Innanzitutto, crea un controller come questo;

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Regular Error";
        return View();
    }

    public ActionResult NotFound404()
    {
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    }
}

Quindi creare la vista in "Views / Error / Index.cshtml" come;

 @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }                     
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

Quindi aggiungi quanto segue nel file asax globale come di seguito:

protected void Application_Error(object sender, EventArgs e)
{
        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        {
            routeData.Values["action"] = "Index";
        }
        else
        {
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
        } 
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();
}

Se dopo aver eseguito questa operazione ottieni ancora la pagina di errore IIS personalizzata, assicurati che le seguenti sezioni siano commentate (o vuote) nel file di configurazione web:

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>

Non credo che questo approccio funzionerà in tutti i casi, poiché un 404 viene spesso intercettato dal server web e quindi non viene mai gestito a livello di applicazione.
Chris Halcrow

Voglio aggiungere che se segui questo approccio, consiglierei di aggiungere un Response.End();alla fine del tuo gestore Application_Error. Senza questo, viene attivata solo la prima occorrenza di un errore per una determinata sessione, il che è un problema quando si ha, ad esempio, la registrazione degli errori personalizzata nel gestore Application_Error.
Keith

6

Se si lavora in MVC 4, è possibile guardare questo soluzione, ha funzionato per me.

Aggiungi il seguente metodo Application_Error al mio Global.asax:

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

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

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

Il controller stesso è davvero semplice:

public class ErrorController : Controller
{
    public ActionResult Index(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        return View();
    }
}

Controlla il codice sorgente completo di Mvc4CustomErrorPage su GitHub .


0

Ho avuto lo stesso problema, la cosa che devi fare è, invece di aggiungere l'attributo customErrors nel file web.config nella tua cartella Views, devi aggiungerlo nel file web.config nella cartella principale dei tuoi progetti


0

Ecco la vera risposta che consente di personalizzare completamente la pagina di errore in un unico posto. Non è necessario modificare web.config o creare codice separato.

Funziona anche in MVC 5.

Aggiungi questo codice al controller:

        if (bad) {
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        }

Basato su http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages


0

Parlerò di alcuni casi specifici,

se stai usando il "metodo PageNotFound" in HomeController come sotto

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

non funzionerebbe questo. Ma devi cancellare i tag Route come di seguito,

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

E se lo cambi come nome del metodo in web.config , funziona. Tuttavia, non dimenticare di eseguire il codice come di seguito in web.config

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.