IIS7 Remplace customErrors lors de la définition de Response.StatusCode?

98

J'ai un problème étrange ici. Tout le monde sait que si vous utilisez la customErrorssection de web.config pour créer une page d'erreur personnalisée, vous devez définir Response.StatusCodece qui est approprié. Par exemple, si je crée une page 404 personnalisée et la nomme 404.aspx, je pourrais mettre <% Response.StatusCode = 404 %>le contenu afin de lui donner un véritable en-tête de statut 404.

Suivez-moi jusqu'ici? Bien. Essayez maintenant de le faire sur IIS7. Je ne peux pas le faire fonctionner, point final. Si Response.StatusCodeest défini dans la page d'erreur personnalisée, IIS7 semble remplacer complètement la page d'erreur personnalisée et affiche sa propre page d'état (si vous en avez une configurée).

Est-ce que quelqu'un d'autre a vu ce comportement et peut-être aussi savoir comment le contourner? Cela fonctionnait sous IIS6, donc je ne sais pas pourquoi les choses ont changé.

Remarque: ce n'est pas le même que le problème dans ASP.NET personnalisé 404 renvoyant 200 OK au lieu de 404 introuvable

Nicolas
la source
Bobby, j'ai trouvé cette question et l'ai essayé, mais cela n'a pas résolu le problème. Mais merci.
Nicholas
Je voudrais faire remarquer que ce problème se produit également lors du passage de la pipe classique à la pipeine intégrée. J'ai utilisé la solution @PavelChuchuva (la solution @RickStrahl fonctionne également). Je suppose que le «passthrough» dans Classic est automatique, dans Integrated, il prend la gestion globale des pages d'erreur du serveur ..
sonjz

Réponses:

116

Définissez existingResponse sur PassThrough dans la section system.webServer / httpErrors:

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

La valeur par défaut de la propriété existingResponse est Auto:

Auto indique au module d'erreur personnalisé de faire la bonne chose. Le texte d'erreur réel vu par les clients sera affecté en fonction de la valeur de fTrySkipCustomErrors renvoyée lors de l' IHttpResponse::GetStatusappel. Lorsque fTrySkipCustomErrors est défini sur true, le module d'erreur personnalisé laisse passer la réponse, mais s'il est défini sur false, le module d'erreur personnalisé remplace le texte par son propre texte.

Plus d'informations: à quoi s'attendre du module d'erreur personnalisé IIS7

Pavel Chuchuva
la source
3
Notez que la définition de existingResponse sur PassThrough peut entraîner des effets secondaires. Veuillez maîtriser le lien fourni par Pavel avant toute modification.
Lex Li
Sont-ils <httpErrors existingResponse="PassThrough" />équivalents Response.TrySkipIisCustomErrorsou se comportent-ils différemment?
Asbjørn Ulsberg
1
@sbjornu Ils réalisent la même chose, mais avec Response.TrySkipIisCustomErrorsvous obtenez un meilleur contrôle quand afficher les erreurs personnalisées IIS.
Pavel Chuchuva
merci, j'ai vu beaucoup d'informations sur response.tryskipiiscustomerrors mais pas tellement sur existingresponse.
HBCondo
J'ai résolu un problème avec les pages d'erreur personnalisées qui ne fonctionnaient pas sur mon hôte Web exécutant IIS7 en définissant simplement existingResponse = "Auto", ce qui était très surprenant puisque l'article faisait référence aux revendications par défaut. Ce n'est clairement pas le cas ... ou ma société d'hébergement a défini la mauvaise valeur par défaut ailleurs, je suppose. Quoi qu'il en soit, j'espère que cela fera gagner quelques heures à quelqu'un: \
Eric Sassaman
80

Le moyen le plus simple de rendre le comportement cohérent consiste à effacer l'erreur et à utiliser Response.TrySkipIisCustomErrors et à le définir sur true. Cela remplacera la gestion de la page d'erreur globale IIS depuis votre page ou le gestionnaire d'erreur global dans Application_Error.

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

En règle générale, vous devez le faire dans votre gestionnaire Application_Error qui gère toutes les erreurs que vos gestionnaires d'erreurs d'application ne détectent pas.

Des informations plus détaillées peuvent être trouvées dans cet article de blog: http://www.west-wind.com/weblog/posts/745738.aspx

Rick Strahl
la source
2
Cela ne fonctionne pas non plus pour moi (IIS8), et les conseils ne semblent pas correspondre à l'OP (en supposant que je le lis correctement). Je veux que le customErrorconfiguré dans Web.config se déclenche. Avec Response.TrySkipIisCustomErrors = truej'obtiens le même comportement: la vilaine page d'erreur générée par le serveur s'affiche. Avec lui, falserien ne se passe - une fenêtre de navigateur vide.
Shawn South
A bien fonctionné pour moi! Bien que le paramètre mentionné par Pavel Chuchuva dans sa réponse fonctionne également, il a eu des effets secondaires qui ont causé d'autres problèmes. Ce paramètre m'a permis d'ignorer le remplacement d'erreur IIS dans le scénario spécifique que je voulais, tout en laissant le comportement intact pour tout le reste.
Kevin Tighe
A bien fonctionné dans Azure pour moi. En-têtes de serveurServer:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET
oxfn
Je trouve toujours que je dois régler customErrors mode="Off"pour que cela fonctionne. Si je fais cela, alors le httpErrors existingResponse = "Auto" (la valeur par défaut) fonctionne correctement pour moi lorsque j'utilise le code dans cette réponse.
AaronLS
11

Résolu: Il s'avère que «Erreurs détaillées» doit être activée pour qu'IIS7 «contournent» toute page d'erreur que vous pourriez avoir. Voir http://forums.iis.net/t/1146653.aspx

Nicolas
la source
1
Bien que celle-ci ait été marquée comme la réponse, je pense que cela vaut la peine de lire d'autres réponses pour obtenir plus d'informations sur le sujet.
Lex Li
Il pourrait également être bon de supprimer. HandleErrorAttribute dans FilterConfig
Per G
4

Je ne sais pas si c'est de nature similaire ou non, mais j'ai résolu un problème qui semble similaire en surface et voici comment je l'ai géré.

Tout d'abord, la valeur par défaut pour existingResponse (Auto) était la bonne réponse dans mon cas, puisque j'ai un personnalisé 404, 400 et 500 (je pourrais en créer d'autres, mais ces trois suffiront pour ce que je fais). Voici les sections pertinentes qui m'ont aidé.

Depuis web.config:

<customErrors mode="Off" />

Et

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

À partir de là, j'ai ajouté ceci dans Application_Error sur global.asax:

    Response.TrySkipIisCustomErrors = True

Sur chacune de mes pages d'erreur personnalisées, je devais inclure le code d'état de réponse correct. Dans mon cas, j'utilise un 404 personnalisé pour envoyer les utilisateurs vers différentes sections de mon site, donc je ne veux qu'un code d'état 404 soit renvoyé à moins qu'il ne s'agisse en fait d'une page morte.

Bref, c'est comme ça que je l'ai fait. J'espère que cela aide quelqu'un.

SEFL
la source
3

Ce problème a été un casse-tête majeur. Aucune des suggestions précédemment mentionnées ne l'a résolu à elle seule, donc j'inclus ma solution. Pour mémoire, notre environnement / plateforme utilise:

  • .NET Framework 4
  • MVC 3
  • IIS8 (poste de travail) et IIS7 (serveur Web)

Plus précisément, j'essayais d'obtenir une réponse HTTP 404 qui redirigerait l'utilisateur vers notre page 404 personnalisée (via les paramètres Web.config).

Tout d'abord, mon code devait lancer un fichier HttpException. Le retour d'un NotFoundResultdu contrôleur n'a pas obtenu les résultats que j'attendais.

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

Ensuite , je devais configurer à la fois les customErrorset les httpErrornoeuds dans le 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>

Notez que je suis parti le existingResponsecommeAuto , qui est différent de la solution @sefl fournie.

Les customErrorsparamètres semblaient nécessaires pour gérer mon jeté explicitement HttpException, tandis que lehttpErrors nœud gérait les URL qui ne faisaient pas partie des modèles de route spécifiés dans Globals.asax.cs.

PS Avec ces paramètres, je n'ai pas besoin de définir Response.TrySkipIisCustomErrors

Shawn Sud
la source
2

TrySkipIisCustomErrorsn'est qu'une partie d'un puzzle. Si vous utilisez des pages d'erreur personnalisées mais que vous souhaitez également fournir du contenu RESTful basé sur les statuts 4xx, vous avez un problème. La définition de httpErrors.existingResponse de web.config sur "Auto" ne fonctionne pas, car .net semble toujours livrer du contenu de page à IIS, donc l'utilisation de "Auto" entraîne la non-utilisation de toutes (ou du moins de certaines) pages d'erreur personnalisées. L'utilisation de "Remplacer" ne fonctionnera pas non plus, car la réponse contiendra votre code d'état http, mais son contenu sera vide ou rempli d'une page d'erreur personnalisée. Et le "PassThrough" désactive en fait le CEP, donc il ne peut pas être utilisé.

Donc, si vous souhaitez contourner le CEP dans certains cas (en contournant je veux dire en retournant le statut 4xx avec du contenu), vous aurez besoin d'une étape supplémentaire: nettoyez l'erreur:

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

Donc, si vous voulez utiliser la réponse REST (c'est-à-dire 400 - Bad Request) et envoyer du contenu avec elle, il vous suffira de définir TrySkipIisCustomErrorsquelque part dans l'action et de définir existingResponsesur "Auto" dans la section httpErrors de web.config. Maintenant:

  • lorsqu'il n'y a pas d'erreur (l'action renvoie 4xx ou 5xx) et que du contenu est renvoyé, le CEP n'est pas utilisé et le contenu est passé au client;
  • lorsqu'il y a une erreur (une exception est levée), le contenu renvoyé par les gestionnaires d'erreurs est supprimé, donc le CEP est utilisé.

Si vous souhaitez renvoyer le statut avec un contenu vide de votre action, il sera traité comme une réponse vide et CEP sera affiché, il y a donc de la place pour améliorer ce code.

Łukasƨ Fronczyk
la source
0

Par défaut, IIS 7 utilise des messages d'erreur personnalisés détaillés, donc je suppose que Response.StatusCode sera égal à 404.XX plutôt qu'à seulement 404.

Vous pouvez configurer IIS7 pour utiliser les codes de message d'erreur plus simples ou modifier votre code en gérant les messages d'erreur plus détaillés qu'offre IIS7.

Plus d'informations disponibles ici: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

Une enquête plus approfondie a révélé que je l'avais mal tourné - les messages détaillés ne sont pas par défaut, mais ils ont peut-être été activés sur votre boîte si vous voyez les différents messages d'erreur que vous avez mentionnés.

nullnvoid
la source
Response.StatusCode est un entier, donc je ne vois pas de moyen de définir un code plus spécifique que simplement "404". J'ai configuré IIS7 pour utiliser / afficher des pages d'erreur personnalisées, comme l'indique votre URL.
Nicholas
Hmmm ... Malheureusement, je ne peux pas tester pour le moment car je ne suis pas sur mon ordinateur personnel. Si vous n'avez pas de solution d'ici là, je vais jeter un coup d'œil ce soir.
nullnvoid