77 votes

Le serveur ne peut pas définir le statut après l'envoi des en-têtes HTTP IIS7.5

Parfois, j'obtiens une exception dans mon environnement de production :

  • Informations sur le processus
    • ID du processus : 3832
    • Nom du processus : w3wp.exe
    • Nom du compte : NT AUTHORITY\NETWORK SERVICE
  • Informations sur l'exception
    • Type d'exception : System.Web.HttpException
    • Message d'exception : Le serveur ne peut pas définir l'état après l'envoi des en-têtes HTTP.
  • Informations sur la demande
    • URL de la demande : http://www.myulr.pl/logon
    • Chemin de la demande : /logon
    • Adresse de l'hôte utilisateur : 10.11.9.1
    • Utilisateur : user001
    • Est authentifié : Vrai
    • Type d'authentification : Forms
    • Nom du compte du fil : NT AUTHORITY\NETWORK SERVICE
  • Informations sur le fil
    • ID du fil : 10
    • Nom du compte du fil : NT AUTHORITY\NETWORK SERVICE
    • Impersonation : Faux
Trace de la pile : at System.Web.HttpResponse.set_StatusCode(Int32 value) at  
System.Web.HttpResponseWrapper.set_StatusCode(Int32 value) at  
System.Web.Mvc.HandleErrorAttribute.OnException(ExceptionContext filterContext) at  
System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList(1) filters, Exception exception) at  
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) at System.Web.Mvc.Controller.ExecuteCore() at  
System.Web.Mvc.MvcHandler.<>c__DisplayClass8.b__4() at  
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.b__0() at  
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8(1).b__7(IAsyncResult _) at  
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult(1).End() at   
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) at  
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at  
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& ompletedSynchronously) 

Je n'ai pas remarqué cette erreur sur mon environnement de test, que devrais-je vérifier ?

J'utilise ASP.NET MVC 2 (Release Candidate 2)

0 votes

Cela m'arrive aussi. L'erreur provient de l'HandleErrorAttribute, comme dans votre cas.

1 votes

Avez-vous pu résoudre ce problème?

3 votes

J'ai eu le même problème depuis que je suis passé à MVC 2. De plus, lors de la définition des cookies, une erreur similaire se produit - cela ne peut pas arriver après l'envoi des en-têtes. Je suis curieux de la réponse. Dans mon cas, basculer entre http/https semble jouer un rôle.

64voto

stephbu Points 4440

Je suis largement d'accord avec Vagrant sur la cause:

  1. vos actions exécutaient, écrivant des balises dans le flux de réponse
  2. le flux était non tamponné, obligeant les en-têtes de réponse à être écrits avant que l'écriture des balises puisse commencer.
  3. Votre vue a rencontré une erreur d'exécution
  4. Le gestionnaire d'exceptions entre en jeu en essayant de définir le code d'état sur quelque chose d'autre que 200
  5. Échoue car les en-têtes ont déjà été envoyés.

La où je ne suis pas d'accord avec Vagrant, c'est sur le remède "ne cause pas d'erreurs en liaison" - vous pourriez toujours rencontrer des erreurs d'exécution dans la liaison de la vue par exemple des exceptions de référence nulle.

Une meilleure solution pour cela est de s'assurer que Response.BufferOutput = true; avant que des octets ne soient envoyés au flux de réponse. par exemple dans votre action de contrôleur ou dans On_Begin_Request de l'application. Cela permet le transfert de serveurs, les cookies/les en-têtes à être définis etc. jusqu'à la fin naturelle de la réponse, ou l'appel de fin/vidage.

Bien sûr, vérifiez également que le tampon n'est pas vidé/défini sur faux plus bas dans la pile.

Référence MSDN: HttpResponse.BufferOutput

1 votes

Je reçois la même erreur mais dans mon cas, cela se produit lorsque j'essaie d'appeler une action enfant. J'ai essayé de définir Response.BufferOutput = true au début de l'action parent mais cela n'a pas aidé. Des idées ?

0 votes

Samo, quelque part plus tôt dans votre code, quelque chose écrit des octets dans le flux de réponse, définissez le tamponnage mu au début du traitement de la demande, par exemple avant de laisser votre Action commencer dans votre contrôleur.

0 votes

Comment utiliser HttpResponse.BufferOutput dans un contrôleur MVC ?

53voto

Doug Points 3948

Juste pour ajouter aux réponses ci-dessus. J'ai eu le même problème lorsque j'ai commencé à utiliser ASP.Net MVC et que je faisais un Response.Redirect pendant une action de contrôleur :

Response.Redirect("/blah", true);

Au lieu de retourner une action Response.Redirect je devrais retourner une action RedirectAction :

return Redirect("/blah");

1 votes

Merci, je faisais la même chose dans mon filtre. Je l'ai modifié et cela a été résolu... //Assistant URL pour générer l'URL de redirection. UrlHelper urlHelper = new UrlHelper(filterContext.RequestContext); filterContext.Result = new RedirectResult(urlHelper.Action(ActionNames.Index, ControllerNames.CustomerSearch, new{Area = ""})); //à la fin base.OnActionExecuting(filterContext);

2 votes

J'ai eu un problème similaire impliquant le client CAS .NET et cette réponse m'a mis sur la piste de mon problème. Je retournais essentiellement une réponse 'deux fois', en appelant CasAuthentication.SingleSignOut(); suivi d'un RedirectToAction(). Évidemment, cela n'a pas de sens -- comment peut-on rediriger deux fois, n'est-ce pas? Mais je ne m'en suis pas rendu compte à ce moment-là. J'ai changé le type de retour de mon action LogOut de ActionResult à void, supprimé la redirection, et le problème a été résolu. Merci!

17voto

Vagrant Points 1259

Le serveur HTTP ne renvoie pas l'en-tête de réponse au client tant que vous n'avez pas spécifié une erreur ou que vous ne commencez pas à envoyer des données. Si vous commencez à renvoyer des données au client, le serveur doit d'abord envoyer l'en-tête de réponse (qui contient le code de statut). Une fois l'en-tête envoyé, vous ne pouvez plus spécifier de code de statut dans l'en-tête, évidemment.

Voici le problème habituel. Vous démarrez la page et envoyez certaines balises initiales (c'est-à-dire ). Le serveur envoie ensuite ces balises au client, après avoir envoyé l'en-tête de réponse HTTP avec un statut de SUCCÈS supposé. Maintenant, vous commencez à travailler sur le contenu de la page et découvrez un problème. Vous ne pouvez pas envoyer une erreur à ce stade car l'en-tête de réponse, qui contiendrait le statut d'erreur, a déjà été envoyé.

La solution est la suivante: Avant de générer du contenu, vérifiez s'il y a des erreurs. Seulement alors, lorsque vous avez assuré qu'il n'y aura pas de problèmes, vous pouvez commencer à envoyer du contenu, comme la balise .

Dans votre cas, il semble que vous ayez une page de connexion qui traite une demande POST à partir d'un formulaire. Vous jetez probablement un peu de HTML initial, puis vérifiez si le nom d'utilisateur et le mot de passe sont valides. Au lieu de cela, vous devriez d'abord authentifier l'utilisateur/mot de passe, avant de générer n'importe quel HTML.

13voto

VahidN Points 3905

J'ai eu le même problème en définissant StatusCode puis Response.End dans la méthode HandleUnauthorizedRequest de AuthorizeAttribute

var ctx = filterContext.HttpContext;
ctx.Response.StatusCode = (int)HttpStatusCode.Forbidden;
ctx.Response.End();

Si vous utilisez .NET 4.5+, ajoutez cette ligne avant Response.StatusCode

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

Si vous utilisez .NET 4.0, essayez SuppressFormsAuthenticationRedirectModule.

1 votes

Aussi, notez que Response.End(); par lui-même pose problème également, car il envoie implicitement un code d'état HTTP 200. En général, on ne devrait probablement pas manipuler l'objet Response manuellement, mais plutôt générer/renvoyer une exception/object de réponse approprié(e) et laisser ASP.NET faire son travail.

11voto

Sandeep Points 21

Que diriez-vous de vérifier ceci avant de rediriger :

if (!Response.IsRequestBeingRedirected)
{
   //faire la redirection
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X