System.Threading.ThreadAbortException bei Verwendung von Server.Transfer in HTTPHandler in einer ASP.NET Anwendung

Dieser Artikel hilft Ihnen, das Problem zu beheben, dass ein Fehler ausgelöst werden kann, wenn Sie eine Server.Transfer Methode zum Übertragen des HTTPHandler Steuerelements von einer Seite auf eine andere in einer ASP.NET Webanwendung verwenden.

Ursprüngliche Produktversion:   ASP.NET
Ursprüngliche KB-Nummer:   817266

Problembeschreibung

Wenn Sie eine Methode zum Server.Transfer HTTPHandler Übertragen des Steuerelements von einer Seite auf eine andere in einer ASP.NET Webanwendung verwenden, wird möglicherweise die folgende Fehlermeldung angezeigt:

System.Threading.ThreadAbortException: Der Thread wurde abgebrochen. Auf
System.Threading.Thread.AbortInternal() at System.Threading.Thread.Abort() at
System.Threading.Thread.Abort(Object stateInfo) at System.Web.HttpResponse.End() at
System.Web.HttpServerUtility.Transfer(String path, Boolean preserveForm)

Ursache

Beim Aufrufen ruft Server.Transfer ASP.NET die Methode intern Server.Execute auf, um das Steuerelement zu übertragen, und ruft die Response.End Methode auf, um die Verarbeitung der aktuellen Seite zu beenden. Response.End beendet die Seitenausführung und ruft die Thread.Abort Methode auf. Die Thread.Abort Methode bewirkt, dass die ThreadAbortException Fehlermeldung angezeigt wird.

Problemumgehung

Um dieses Problem zu umgehen, verwenden Sie Server.Execute statt in der Methode von Server.Transfer ProcessRequest HTTPHandler . Die geänderte ProcessRequest Methode lautet wie folgt:

Visual C# .NET-Beispielcode

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 .NET-Beispielcode

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

Status

Es handelt sich hierbei um ein beabsichtigtes Verhalten.

Schritte zum Reproduzieren des Verhaltens

  1. Verwenden Sie in Microsoft Visual Studio .NET Visual Basic .NET oder Visual C# .NET, um ein neues ASP.NET Webanwendungsprojekt zu erstellen. Standardmäßig wird WebForm1.aspx erstellt. Benennen Sie das Projekt ServerTransferTest.

  2. Klicken Sie mit der rechten Maustaste auf "WebForm1.aspx", und wählen Sie "HTML-Quelle anzeigen" aus.

  3. Ersetzen Sie den vorhandenen Code durch den folgenden Beispielcode:

    <%@ 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. Doppelklicken Sie auf die Entwurfsansicht von WebForm1.aspx, und ersetzen Sie dann den beendenden Code auf der CodeBehind-Seite durch den folgenden Beispielcode:

    Visual C# .NET-Beispielcode

    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 .NET-Beispielcode

    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. Wählen Sie im Menü "Datei" die Option "Neues Element hinzufügen" aus.

  6. Wählen Sie unter "Neues Element hinzufügen" die Option "Klasse" aus. Benennen Sie im Textfeld "Name" unter "Neues Element hinzufügen" die Klasse HelloWorldHandler um, und klicken Sie dann auf "Öffnen".

  7. Ersetzen Sie den vorhandenen Code in der HelloWorldHandler Klassendatei durch den folgenden Beispielcode:

    Visual C# .NET-Beispielcode

    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 .NET-Beispielcode

    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. Wiederholen Sie die Schritte 5 und 6, um eine weitere Klassendatei hinzuzufügen. Benennen Sie die Klassendatei HelloWorldHandlerFactory um.

  9. Ersetzen Sie den vorhandenen Code in der HelloWorldHandlerFactory Klassendatei durch den folgenden Beispielcode:

    Visual C# .NET-Beispielcode

    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 .NET-Beispielcode

    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. Öffnen Sie die Web.config Datei, und fügen Sie den <httpHandlers> Abschnitt im Abschnitt wie folgt <system.web> hinzu:

    <configuration>
        <system.web>
            <httpHandlers>
                <add verb="*" path="*.ashx" type="ServerTransferTest.HelloWorldHandlerFactory,ServerTransferTest" />
            </httpHandlers>
        .....
        </system.web>
    </configuration>
    
  11. Wählen Sie im Menü "Debuggen" die Option "Start" aus, und klicken Sie dann auf den folgenden Hyperlink auf "WebForm1.aspx":
    http://localhost/ServerTransferTest/test.ashx

References