web-dev-qa-db-fra.com

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

Avoir un problème étrange ici. Tout le monde sait que si vous utilisez la section customErrors de web.config pour créer une page d'erreur personnalisée, vous devez définir votre Response.StatusCode sur la valeur appropriée. Par exemple, si je crée une page 404 personnalisée et que je la nomme 404.aspx, je pourrais mettre <% Response.StatusCode = 404 %> dans le contenu afin de lui donner un en-tête de statut 404.

Suivez-moi jusqu'à présent? Bien. Maintenant, essayez de faire cela sur IIS7. Je ne peux pas le faire fonctionner, point final. Si Response.StatusCode est 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 configurée une).

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: Il ne s'agit pas du même problème que dans ASP.NET Custom 404 renvoyant 200 OK au lieu de 404 non trouvé

97
Nicholas Head

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 dit au module d'erreur personnalisé de faire la chose right. Le texte d'erreur réel vu par les clients sera affecté en fonction de la valeur de fTrySkipCustomErrors renvoyée dans l'appel IHttpResponse::GetStatus. Lorsque fTrySkipCustomErrors est défini sur true, le module d'erreur personnalisé laissera passer la réponse, mais s'il est défini sur false, le module d'erreur personnalisé remplace le texte par son propre texte.

Informations complémentaires: À quoi s'attendre du module d'erreur personnalisé IIS7

115
Pavel Chuchuva

Le moyen le plus simple de rendre le comportement cohérent est d'effacer l'erreur et d'utiliser Response.TrySkipIisCustomErrors et de le définir sur true. Cela annulera le traitement de la page d'erreur globale IIS à partir de 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’erreur d’application ne détectent pas.

Vous trouverez des informations plus détaillées dans cet article de blog: http://www.west-wind.com/weblog/posts/745738.aspx

80
Rick Strahl

Résolu: Il s'avère que "les erreurs détaillées" doivent être activées pour que IIS7 "répande" toute page d'erreur que vous pourriez avoir. Voir http://forums.iis.net/t/1146653.aspx

11
Nicholas Head

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

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

De 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 de statut de réponse correct. Dans mon cas, j'utilise un 404 personnalisé pour envoyer des utilisateurs à différentes sections de mon site. Je ne souhaite donc pas demander un code d'état 404. à moins que ce ne soit réellement une page morte.

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

4
SEFL

Ce problème a été un mal de tête majeur. Aucune des suggestions mentionnées précédemment ne l'a résolu pour moi, alors j'inclus ma solution. Pour mémoire, notre environnement/plateforme utilise:

  • .NET Framework 4
  • MVC 3
  • IIS8 (station 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).

Premièrement, mon code devait lancer une HttpException. Le renvoi d'une NotFoundResult du contrôleur n'a pas donné les résultats escomptés.

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

Ensuite, j'ai dû configurer les deux les nœuds customErrors et httpError dans le fichier 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 j'ai laissé la existingResponse sous la forme Auto, ce qui est différent de la solution fournie par @sefl.

Les paramètres customErrors semblaient être nécessaires pour gérer ma HttpException explicitement générée, tandis que le nœud httpErrors gérait les URL ne correspondant pas aux modèles de routage spécifiés dans Globals.asax.cs.

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

3
Shawn South

Par défaut, IIS 7 utilise des messages d'erreur personnalisés détaillés. Je suppose donc que Response.StatusCode sera égal à 404.XX au lieu de 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 proposés par 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 j’avais mal interprété le message. Les messages détaillés ne le 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 mentionnés.

0
nullnvoid

TrySkipIisCustomErrors n'est qu'une partie d'un puzzle. Si vous utilisez des pages d'erreur personnalisées mais souhaitez également fournir du contenu RESTful basé sur des statuts 4xx, vous rencontrez un problème. La définition de httpErrors.existingResponse de web.config sur "Auto" ne fonctionne pas, car .net semble toujours fournir une partie du contenu de la page à IIS. Par conséquent, l'utilisation de "Auto" empêche l'utilisation de toutes les pages d'erreur personnalisées. Utiliser "Remplacer" ne fonctionnera pas non plus, car la réponse contiendra votre code de statut http, mais son contenu sera vide ou rempli avec la page d'erreur personnalisée. Et le "PassThrough" désactive le CEP, il ne peut donc pas être utilisé.

Donc, si vous voulez contourner CEP dans certains cas (en évitant de renvoyer le statut 4xx avec du contenu), vous aurez besoin d'une étape supplémentaire: effacez 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 - Requête incorrecte) et envoyer du contenu avec elle, il vous suffira de définir TrySkipIisCustomErrors quelque part dans l'action et de définir existingResponse sur "Auto" dans la section httpErrors de web.config. . À présent:

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

Si vous souhaitez renvoyer un statut avec un contenu vide de votre action, il sera traité comme une réponse vide et le message CEP s'affichera. Il est donc possible d'améliorer ce code.

0
Łukasƨ Fronczyk