web-dev-qa-db-ja.com

HTTPヘッダーがIIS7.5に送信された後、サーバーはステータスを設定できません

実稼働環境で例外が発生する場合があります。

  • プロセス情報
    • プロセスID:3832
    • プロセス名:w3wp.exe
    • アカウント名:NT AUTHORITY\NETWORK SERVICE
  • 例外情報
    • 例外の種類:System.Web.HttpException
    • 例外メッセージ:HTTPヘッダーが送信された後、サーバーはステータスを設定できません。
  • リクエスト情報
    • リクエストURL: http://www.myulr.pl/logon
    • 要求パス:/ logon
    • ユーザーホストアドレス:10.11.9.1
    • ユーザー:user001
    • 認証済み:True
    • 認証タイプ:フォーム
    • スレッドアカウント名:NT AUTHORITY\NETWORK SERVICE
  • スレッド情報
    • スレッドID:10
    • スレッドアカウント名:NT AUTHORITY\NETWORK SERVICE
    • なりすまし:偽
Stack trace: 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.<BeginProcessRequest>b__4() at  
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0() at  
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8(1).<BeginSynchronous>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) 

テスト環境でこのエラーに気付いていませんでしたが、何を確認すればよいですか?

ASP.NET MVC 2(リリース候補2)を使用しています

69
marcinn

私は、Vagrantにその原因について広く同意します。

  1. アクションが実行され、応答ストリームにマークアップが書き​​込まれました
  2. ストリームはバッファリングされず、マークアップの書き込みを開始する前に応答ヘッダーが強制的に書き込まれました。
  3. ビューでランタイムエラーが発生しました
  4. 例外ハンドラーは、ステータスコードを200以外の何かに設定しようと試みます。
  5. ヘッダーが既に送信されているため失敗します。

Vagrantに反対するのは、「バインディングにエラーが発生しない」救済策です。Viewバインディングでランタイムエラーが発生する可能性があります。 null参照例外。

これに対するより良い解決策は、Response.BufferOutput = true;は、任意のバイトが応答ストリームに送信される前。例えばコントローラアクションまたはアプリケーションのOn_Begin_Requestで。これにより、サーバー転送、Cookie /ヘッダーの設定などを、自然に終了する応答まで、または終了/フラッシュを呼び出すまで可能にします。

もちろん、スタック内でバッファがさらにフラッシュ/ falseに設定されていないことも確認してください。

MSDNリファレンス: HttpResponse.BufferOutput

59
stephbu

上記の回答に追加するだけです。最初にASP.Net MVCの使用を開始し、コントローラーアクション中にResponse.Redirectを実行していたときに、同じ問題が発生しました。

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

Response.Redirectアクションを返す代わりに、RedirectActionを返す必要があります。

return Redirect("/blah");
45
Doug

HTTPサーバーは、エラーを指定するか、データの送信を開始するまで、応答ヘッダーをクライアントに送り返しません。クライアントへのデータの送信を開始する場合、サーバーは最初に応答ヘッド(ステータスコードを含む)を送信する必要があります。ヘッダーが送信されると、明らかにヘッダーにステータスコードを挿入できなくなります。

これが通常の問題です。ページを起動し、いくつかの初期タグを送信します(つまり、<head>)。サーバーは、想定された成功ステータスのHTTP応答ヘッダーを最初に送信した後、これらのタグをクライアントに送信します。ここで、ページの内容の作業を開始し、問題を発見します。エラーステータスを含む応答ヘッダーが既に送信されているため、この時点でエラーを送信することはできません。

解決策はこれです:コンテンツを生成する前に、エラーが発生するかどうかを確認します。その後、問題がないことを確認したら、タグなどのコンテンツの送信を開始できます。

あなたの場合、POSTフォームからのリクエストを処理するログインページがあるようです。おそらく最初のHTMLをいくつか捨てて、ユーザー名とパスワードが有効かどうかを確認してください。代わりに、 anyHTMLを生成する前に、まずユーザー/パスワードを認証する必要があります。

15
Vagrant

StatusCodeHandleUnauthorizedRequestメソッドでAuthorizeAttributeを設定してからResponse.Endを設定することで同じ問題が発生しました

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

.NET 4.5+を使用している場合、Response.StatusCodeの前にこの行を追加します

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

.NET 4.0を使用している場合は、 SuppressFormsAuthenticationRedirectModule を試してください。

11
VahidN

リダイレクトを行う前にこれを確認してください:

if (!Response.IsRequestBeingRedirected)
{
   //do the redirect
}
10
Sandeep

実際に、スローする応答があるページをリダイレクトしようとしています。そのため、最初にページの先頭でresponse.buffer = trueを使用してバッファに入れた情報を保持し、次にresponse.flushを使用して必要に応じてフラッシュします。このエラーは修正されます

3
hema

同じエラーが発生していました。そのため、一部の人にとっては便利かもしれません。

私たちにとって、原因は非常に簡単でした。インターフェイスの変更によりエンドユーザーが混乱し、フォーム送信後の「悪い」時間にブラウザーの戻るボタンを押していました(おそらくPRGパターンを使用する必要がありましたが、しませんでした)。

この問題を修正し、ユーザーは[戻る]ボタンを押さなくなりました。問題が解決しました。

1
niico

この例外の一部を覚えています:「ヘッダー情報を変更できません-ヘッダーは既に送信されています」PHPで発生します。ヘッダーがリダイレクトフェーズで既に送信され、他の出力が生成されたときに発生しました。例:

echo "hello"; header( "Location: http://stackoverflow.com ");

私が間違っている場合はご容赦ください。訂正しますが、まだMS Technologiesを学んでいるので、私は助けようとしていました。

1
Adil Mehmood

申し訳ありませんが、同じ問題が発生した場合に備えて、スレッドに2セントを追加しています。

  • MVCアプリでフォーム認証を使用しました
  • ただし、一部のコントローラーアクションは「匿名」でした。つまり、非認証ユーザーに許可されました。
  • 時々それらのアクションで私はstillある条件下でユーザーをログインフォームにリダイレクトさせたい
  • それを行うために-私はアクションメソッドにこれを持っています:return new HttpStatusCodeResult(401)-そしてASP.NETはこれを検出するのにとてもいいです、そしてそれはログインページにユーザーをリダイレクトします!魔法でしょう?適切なReturnUrlパラメーターなどもあります。

しかし、あなたは私がここに着くところを見ますか? I 401を返す。そして、ASP.NETはユーザーをリダイレクトします。これは本質的に302を返します。あるステータスコードが別のステータスコードに置き換えられます。

そして、いくつかのIISサーバー(ほんのいくつか!)がこの例外をスローします。いくつかはそうではありません。-テストserevrにはありません。ケース右o_O)

私の答えは本質的にここで既に述べたことを繰り返していることを知っていますが、この上書きが正確にどこで起こるのかを把握するのが難しい場合があります。

1
jazzcat

まだこの問題が発生している場合:ovverridingの代わりに使用してみてください

 public void OnActionExecuting(ActionExecutingContext context)
    {
        try
        {

            if (!HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (!HttpContext.Current.Response.IsRequestBeingRedirected)
                {

                    context.Result = new RedirectToRouteResult(
                new RouteValueDictionary {  { "controller", "Login" }, { "action", "Index" } });
                }
            }

        }
        catch (Exception ex)
        {
               new RouteValueDictionary { { "controller", "Login" }, { "action", "Index" } });
        }

    }
0
Emre