次の方法で共有


ASP.NET アプリケーションの HTTPHandler で Server.Transfer を使用したときに System.Threading.ThreadAbortException が発生する

この記事は、HTTPHandlerServer.Transfer メソッドを使用して、ASP.NET Web アプリケーションのあるページから別のページにコントロールを転送したときにエラーがスローされる可能性があるという問題を解決するのに役立ちます。

元の製品バージョン: ASP.NET
元の KB 番号: 817266

現象

HTTPHandlerServer.Transfer メソッドを使用して、ASP.NET Web アプリケーション内のあるページから別のページにコントロールを転送すると、次のエラー メッセージが表示されることがあります。

System.Threading.ThreadAbortException: スレッドを中止しようとしました。 at
System.Threading.Thread.AbortInternal() 場所 System.Threading.Thread.Abort() 場所
System.Threading.Thread.Abort(Object stateInfo) 場所 System.Web.HttpResponse.End() 場所
System.Web.HttpServerUtility.Transfer(String path, Boolean preserveForm)

原因

Server.Transfer を呼び出すと、ASP.NET は内部で Server.Execute メソッドを呼び出してコントロールを転送し、Response.End メソッドを呼び出して現在のページの処理を終了します。 Response.End はページの実行を終了し、Thread.Abort メソッドを呼び出します。 Thread.Abort メソッドを使用すると、ThreadAbortException エラー メッセージが表示されます。

回避策

この問題を回避するには、HTTPHandlerProcessRequest メソッドで Server.Transfer の代わりに Server.Execute を使用します。 変更された ProcessRequest メソッドは次のとおりです。

  • C# コード サンプル

    public void ProcessRequest(HttpContext context)
    {
        try
        {
           context.Server.Execute("WebForm1.aspx");
        }
        catch(System.Exception e)
        {
           context.Response.Write(e.StackTrace);
           context.Response.Write(e.ToString());
        }
    }
    
  • Visual Basic サンプル コード

    Public Sub ProcessRequest(ByVal context As HttpContext) _
           Implements IHttpHandler.ProcessRequest
        Try
           context.Server.Execute("WebForm1.aspx")
        Catch e As Exception
           context.Response.Write(e.StackTrace)
        End Try
    End Sub
    

状態

この動作は仕様によるものです。

動作を再現する手順

  1. Microsoft Visual Studio で、Visual Basic または C# を使用して、Web フォーム アプリケーション プロジェクト ASP.NET 新しいプロジェクトを作成します。 既定では、WebForm1.aspx が作成されます。 プロジェクトに「ServerTransferTest」という名前を付けます。

  2. [WebForm1.aspx] を右クリックし、[HTML ソースの表示] を選択します。

  3. 既存のコードを次のサンプル コードに置き換えます。

    <%@ Page %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
       <HEAD>
          <title>WebForm1</title>
       </HEAD>
       <body MS_POSITIONING="GridLayout">
          <form id="Form1" method="post" runat="server">
             <asp:HyperLink id="HyperLink1" style="Z-INDEX: 101; LEFT: 324px; POSITION: absolute; TOP: 181px" runat="server" NavigateUrl="http://localhost/ServerTransferTest/test.ashx"> http://localhost/ServerTransferTest/test.ashx</asp:HyperLink>
             <asp:Label id="Label1" style="Z-INDEX: 102; LEFT: 292px; POSITION: absolute; TOP: 149px" runat="server">On Clicking this URL should not throw any exception</asp:Label>
          </form>
       </body>
    </HTML>
    
  4. WebForm1.aspxデザイン ビューをダブルクリックし、分離コード ページの終了コードを次のサンプル コードに置き換えます。

    • C# コード サンプル

      using System;
      using System.Web;
      using System.Web.UI.WebControls;
      
      namespace ServerTransferTest
      {
         /// <summary>
         /// Summary description for WebForm1.
         /// </summary>
         public class WebForm1 : System.Web.UI.Page
         {
            protected System.Web.UI.WebControls.Label Label1;
            protected System.Web.UI.WebControls.HyperLink HyperLink1;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
            }
      
            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
               // CODEGEN: ASP.NET Web Form Designer requires this call.
               InitializeComponent();
               base.OnInit(e);
            }
      
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method by using the code editor.
            /// </summary>
            private void InitializeComponent()
            {
               this.Load += new System.EventHandler(this.Page_Load);    
            }
            #endregion
         }
      }
      
    • Visual Basic サンプル コード

      Public Class WebForm1
          Inherits System.Web.UI.Page
          Protected WithEvents Label1 As System.Web.UI.WebControls.Label
          Protected WithEvents HyperLink1 As System.Web.UI.WebControls.HyperLink
      
          'Web Form Designer requires this call.
          <System.Diagnostics.DebuggerStepThrough()>
          Private Sub InitializeComponent()
          End Sub
      
          Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
             'CODEGEN: Web Form Designer requires this method call.
             'Do not modify it by using the code editor.
             InitializeComponent()
          End Sub
      
          Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
             'Put user code to initialize the page here
          End Sub
      End Class
      
  5. [ファイル] メニューで、[新しいアイテムの追加] を選択します。

  6. [新しいアイテムの追加] で、[ クラス] を選択します。 Nameテキスト ボックスの [新しい項目追加クラスHelloWorldHandlerの名前を変更し、Open を選択します。

  7. HelloWorldHandler クラス ファイルの既存のコードを次のサンプル コードに置き換えます。

    • C# コード サンプル

      using System.Web;
      namespace ServerTransferTest
      {
          public class HelloWorldHandler : IHttpHandler
          {
             public void ProcessRequest(HttpContext context)
             {
                try
                {
                   context.Server.Transfer("WebForm1.aspx", true );
                }
                catch(System.Exception e)
                {
                   context.Response.Write(e.StackTrace);
                   context.Response.Write(e.ToString());
                }
             }
             public bool IsReusable
             {
                // To enable pooling, return true here.
                // This keeps the handler in memory.
                get { return false; }
             }
          }
      }
      
    • Visual Basic サンプル コード

      Imports System
      Imports System.Web
      
      Public Class HelloWorldHandler
          Implements IHttpHandler
          Public Sub ProcessRequest(ByVal context As HttpContext) _
             Implements IHttpHandler.ProcessRequest
             Try
                ' context.Server.Transfer("WebForm1.aspx", True)
                context.Server.Execute("WebForm1.aspx")
             Catch e As Exception
                context.Response.Write(e.StackTrace)
             End Try
          End Sub
          ' Override the IsReusable property.
          Public ReadOnly Property IsReusable() As Boolean _
             Implements IHttpHandler.IsReusable
             Get
                Return True
             End Get
          End Property
      End Class
      
  8. 手順 5 と 6 を繰り返して、別のクラス ファイルを追加します。 クラス ファイルの名前を HelloWorldHandlerFactory に変更します。

  9. HelloWorldHandlerFactory クラス ファイルの既存のコードを次のサンプル コードに置き換えます。

    • C# コード サンプル

      using System.Web;
      namespace ServerTransferTest
      {
          public class HelloWorldHandlerFactory : IHttpHandlerFactory
          {
             public IHttpHandler GetHandler( HttpContext context, System.String requestType, System.String url, System.String pathTranslated)
             {
                HttpResponse Response = context.Response;
                Response.Write("<html>");
                Response.Write("<body>");
                Response.Write("<h1> Hello from HelloWorldHandlerFactory.GetHandler </h1>");
                Response.Write("</body>");
                Response.Write("</html>");
                return new HelloWorldHandler();
             }
             public void ReleaseHandler( IHttpHandler handler )
             {
             }
          }
      }
      
    • Visual Basic サンプル コード

      Imports System
      Imports System.Web
      Public Class HelloWorldHandlerFactory
          Implements IHttpHandlerFactory
          Public Overridable Function GetHandler(ByVal context As HttpContext, _
          ByVal requestType As String, ByVal url As String, ByVal pathTranslated As String) _
             As IHttpHandler _
             Implements IHttpHandlerFactory.GetHandler
      
             Dim Response As HttpResponse = context.Response
             Response.Write("<html>")
             Response.Write("<body>")
             Response.Write("<h1> Hello from HelloWorldHandlerFactory.GetHandler </h1>")
             Response.Write("</body>")
             Response.Write("</html>")
             Return New HelloWorldHandler()
          End Function
      
          Public Overridable Sub ReleaseHandler(ByVal handler As IHttpHandler) _
             Implements IHttpHandlerFactory.ReleaseHandler
          End Sub
      End Class
      
  10. web.config ファイルを開き、次のように <system.web> セクションに <httpHandlers> セクションを追加します。

    <configuration>
        <system.web>
            <httpHandlers>
                <add verb="*" path="*.ashx" type="ServerTransferTest.HelloWorldHandlerFactory,ServerTransferTest" />
            </httpHandlers>
        .....
        </system.web>
    </configuration>
    
  11. Debug メニューの Start を選択し、WebForm1.aspxで次のハイパーリンクを選択します。

    http://localhost/ServerTransferTest/test.ashx

関連情報