IIS7 sovrascrive customErrors quando si imposta Response.StatusCode?


98

Ho uno strano problema qui. Tutti sanno che se si utilizza la customErrorssezione web.config per creare una pagina di errore personalizzata, è necessario impostare Response.StatusCodeciò che è appropriato. Ad esempio, se creo una pagina 404 personalizzata e la nomino 404.aspx, potrei inserire <% Response.StatusCode = 404 %>i contenuti in modo che abbia un'intestazione di stato 404 vera.

Mi segui così lontano? Buona. Ora prova a farlo su IIS7. Non riesco a farlo funzionare, punto. Se Response.StatusCodeè impostato nella pagina di errore personalizzata, IIS7 sembra sovrascrivere completamente la pagina di errore personalizzata e mostra la propria pagina di stato (se ne hai una configurata).

Qualcun altro ha visto questo comportamento e forse sa anche come aggirarlo? Funzionava con IIS6, quindi non so perché le cose siano cambiate.

Nota: questo non è lo stesso del problema in ASP.NET personalizzato 404 che restituisce 200 OK invece di 404 non trovato



Bobby, ho effettivamente trovato quella domanda e l'ho provata, ma non ha risolto il problema. Ma grazie.
Nicholas

Vorrei commentare che questo problema si verifica anche quando si passa da pipeine classiche a integrate. Ho usato la soluzione @PavelChuchuva (funziona anche la soluzione @RickStrahl). Immagino che il "passthrough" in Classic sia automatico, in Integrated richiede la gestione della pagina di errore globale del server ..
sonjz

Risposte:


116

Imposta existingResponse su PassThrough nella sezione system.webServer / httpErrors:

  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

Il valore predefinito della proprietà existingResponse è Auto:

Auto dice al modulo di errore personalizzato di fare la cosa giusta . Il testo di errore effettivo visualizzato dai client verrà influenzato a seconda del valore di fTrySkipCustomErrors restituito nella IHttpResponse::GetStatuschiamata. Quando fTrySkipCustomErrors è impostato su true, il modulo di errore personalizzato lascerà passare la risposta ma se è impostato su false, il modulo di errori personalizzati sostituisce il testo con il proprio testo.

Ulteriori informazioni: cosa aspettarsi dal modulo di errore personalizzato IIS7


3
Tieni presente che l'impostazione di existingResponse su PassThrough può causare alcuni effetti collaterali. Si prega di controllare il collegamento fornito da Pavel prima di qualsiasi modifica.
Lex Li,

È <httpErrors existingResponse="PassThrough" />equivalente Response.TrySkipIisCustomErrorso si comportano in modo diverso?
Asbjørn Ulsberg,

1
@sbjornu Ottengono la stessa cosa ma con Response.TrySkipIisCustomErrorste ottieni un controllo migliore quando visualizzare gli errori personalizzati di IIS.
Pavel Chuchuva

grazie, ho visto molte informazioni su response.tryskipiiscustomerrors ma non tanto sulla risposta esistente.
HBCondo

Ho risolto un problema con le pagine di errore personalizzate che non funzionavano sul mio host web che esegue IIS7 semplicemente impostando existingResponse = "Auto", il che è stato molto sorprendente poiché l'articolo fa riferimento afferma che è l'impostazione predefinita. Chiaramente non lo è ... o la mia società di hosting ha impostato il valore predefinito sbagliato altrove, suppongo. Ad ogni modo spero che questo
faccia

80

Il modo più semplice per rendere coerente il comportamento è cancellare l'errore e utilizzare Response.TrySkipIisCustomErrors e impostarlo su true. Ciò sovrascriverà la gestione della pagina di errore globale di IIS dall'interno della pagina o il gestore di errori globale in Application_Error.

Server.ClearError();
Response.TrySkipIisCustomErrors = true;

In genere dovresti farlo nel tuo gestore Application_Error che gestisce tutti gli errori che i gestori degli errori dell'applicazione non rilevano.

Informazioni più dettagliate possono essere trovate in questo post del blog: http://www.west-wind.com/weblog/posts/745738.aspx


2
Anche questo non funziona per me (IIS8) e il consiglio non sembra corrispondere all'OP (supponendo che lo stia leggendo correttamente). Voglio che il customErrorconfigurato in Web.config si attivi. Con Response.TrySkipIisCustomErrors = trueottengo lo stesso comportamento: viene visualizzata la brutta pagina di errore generata dal server. Con esso impostato su falsenon accade nulla: una finestra del browser vuota.
Shawn South,

Ha funzionato bene per me! Anche se l'impostazione menzionata da Pavel Chuchuva nella sua risposta ha funzionato, ha avuto alcuni effetti collaterali che hanno causato altri problemi. Questa impostazione mi consente di saltare l'override dell'errore IIS nello scenario specifico che volevo, lasciando intatto il comportamento per tutto il resto.
Kevin Tighe

Ha funzionato bene in Azure per me. Intestazioni del serverServer:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET
oxfn

Trovo ancora che devo impostare customErrors mode="Off"perché funzioni. Se lo faccio, allora httpErrors existingResponse = "Auto" (l'impostazione predefinita) funziona correttamente per me quando utilizzo il codice in questa risposta.
AaronLS

11

Risolto: risulta che "Errori dettagliati" deve essere attivo affinché IIS7 possa "passare" a qualsiasi pagina di errore che potresti avere. Vedi http://forums.iis.net/t/1146653.aspx


1
Sebbene questa sia stata contrassegnata come la risposta, penso che valga la pena leggere altre risposte per ottenere maggiori informazioni sull'argomento.
Lex Li

Inoltre potrebbe essere utile rimuovere. HandleErrorAttribute in FilterConfig
Per G

4

Non sono sicuro se questo sia di natura simile o meno, ma ho risolto un problema che suona simile in superficie ed ecco come l'ho gestito.

Prima di tutto, il valore predefinito per existingResponse (Auto) era la risposta corretta nel mio caso, poiché ho un 404, 400 e 500 personalizzato (potrei crearne altri, ma questi tre saranno sufficienti per quello che sto facendo). Ecco le sezioni pertinenti che mi hanno aiutato.

Da web.config:

<customErrors mode="Off" />

E

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/errors/404.aspx" responseMode="ExecuteURL" />
  <error statusCode="500" path="/errors/500.aspx" responseMode="ExecuteURL" />
  <error statusCode="400" path="/errors/400.aspx" responseMode="ExecuteURL" />
</httpErrors>

Da lì, l'ho aggiunto in Application_Error su global.asax:

    Response.TrySkipIisCustomErrors = True

In ciascuna delle mie pagine di errore personalizzate dovevo includere il codice di stato della risposta corretto. Nel mio caso, sto usando un 404 personalizzato per inviare gli utenti a diverse sezioni del mio sito, quindi non lo faccio voglio che venga restituito un codice di stato 404 a meno che non sia effettivamente una pagina morta.

Comunque, è così che l'ho fatto. Spero che aiuti qualcuno.


3

Questo problema è stato un grave mal di testa. Nessuno dei suggerimenti menzionati in precedenza da solo mi ha risolto, quindi includo la mia soluzione. Per la cronaca, il nostro ambiente / piattaforma utilizza:

  • .NET Framework 4
  • MVC 3
  • IIS8 (workstation) e IIS7 (web server)

In particolare, stavo cercando di ottenere una risposta HTTP 404 che reindirizzasse l'utente alla nostra pagina 404 personalizzata (tramite le impostazioni Web.config).

Innanzitutto, il mio codice doveva lanciare un file HttpException. Restituire un NotFoundResultdal controller non ha ottenuto i risultati che cercavo.

throw new HttpException(404, "There is no class with that subject");

Poi ho dovuto configurare sia l' customErrorse httpErrornodi nel web.config.

<customErrors mode="On" defaultRedirect="/classes/Error.aspx">
  <error statusCode="404" redirect="/classes/404.html" />
</customErrors>

...

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/classes/404.aspx" responseMode="ExecuteURL" />
</httpErrors>

Nota che ho lasciato l' existingResponseasAuto , che è diverso dalla soluzione fornita da @sefl.

Le customErrorsimpostazioni sembravano necessarie per gestire il mio lancio esplicito HttpException, mentre il filehttpErrors nodo gestiva gli URL che non rientravano nei modelli di percorso specificati in Globals.asax.cs.

PS Con queste impostazioni non avevo bisogno di impostare Response.TrySkipIisCustomErrors


2

TrySkipIisCustomErrorsè solo una parte di un puzzle. Se utilizzi pagine di errore personalizzate ma desideri anche fornire alcuni contenuti RESTful basati sugli stati 4xx, hai un problema. L'impostazione di httpErrors.existingResponse di web.config su "Auto" non funziona, perché .net sembra fornire sempre alcuni contenuti della pagina a IIS, quindi l'utilizzo di "Auto" fa sì che tutte (o almeno alcune) pagine di errore personalizzate non vengano utilizzate. Anche l'utilizzo di "Sostituisci" non funzionerà, perché la risposta conterrà il codice di stato http, ma il suo contenuto sarà vuoto o riempito con una pagina di errore personalizzata. E il "PassThrough" in effetti disattiva il CEP, quindi non può essere utilizzato.

Quindi, se vuoi bypassare CEP per alcuni casi (bypassando intendo restituire lo stato 4xx con alcuni contenuti) avrai bisogno di un passaggio aggiuntivo: pulire l'errore:

void Application_Error(object sender, EventArgs e)
{
    var httpException = Context.Server.GetLastError() as HttpException;
    var statusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;

    Context.Server.ClearError();
    Context.Response.StatusCode = statusCode;
}

Quindi, se vuoi usare la risposta REST (es. 400 - Bad Request) e inviare del contenuto con essa, dovrai solo impostare TrySkipIisCustomErrorsda qualche parte in azione e impostare existingResponsesu "Auto" nella sezione httpErrors in web.config. Adesso:

  • quando non ci sono errori (l'azione restituisce 4xx o 5xx) e viene restituito del contenuto, il CEP non viene utilizzato e il contenuto viene passato al client;
  • quando si verifica un errore (viene generata un'eccezione) il contenuto restituito dai gestori di errori viene rimosso, quindi viene utilizzato il CEP.

Se vuoi restituire lo stato con contenuto vuoto dalla tua azione, verrà considerato come una risposta vuota e verrà mostrato CEP, quindi c'è un po 'di spazio per migliorare questo codice.


0

Per impostazione predefinita, IIS 7 utilizza messaggi di errore personalizzati dettagliati, quindi presumo che Response.StatusCode sarà uguale a 404.XX anziché solo a 404.

È possibile configurare IIS7 per utilizzare i codici dei messaggi di errore più semplici o modificare il codice che gestisce i messaggi di errore più dettagliati offerti da IIS7.

Maggiori informazioni disponibili qui: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

Ulteriori indagini hanno rivelato che avevo sbagliato modo: i messaggi dettagliati non sono di default ma forse sono stati attivati, sulla tua scatola se vedi i diversi messaggi di errore che hai menzionato.


Response.StatusCode è un numero intero, quindi non vedo un modo per impostare un codice più specifico rispetto a "404". Ho IIS7 configurato per utilizzare / mostrare pagine di errore personalizzate, come indica il tuo URL.
Nicholas

Hmmm ... Purtroppo al momento non posso provare perché non sono sul mio PC di casa. Se non hai una soluzione per allora, darò un'occhiata stasera.
nullnvoid il
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.