System.Threading.ThreadAbortException cuando se usa Server.Transfer en HTTPHandler en una ASP.NET aplicación

Este artículo le ayuda a resolver el problema de que se puede lanzar un error al usar un método para transferir el control de una página a otra en una ASP.NET Server.Transfer HTTPHandler web.

Versión del producto original:   ASP.NET
Número KB original:   817266

Síntomas

Cuando usa un método para transferir el control de una página a otra en una aplicación web de ASP.NET, puede recibir Server.Transfer el siguiente mensaje de HTTPHandler error:

System.Threading.ThreadAbortException: se estaba abortando el subproceso. at
System.Threading.Thread.AbortInternal() en System.Threading.Thread.Abort() en
System.Threading.Thread.Abort(Object stateInfo) en System.Web.HttpResponse.End() en
System.Web.HttpServerUtility.Transfer(String path, Boolean preserveForm)

Causa

Al llamar a , ASP.NET llama internamente al método para transferir el control y llama al método para finalizar el procesamiento Server.Transfer Server.Execute de la página Response.End actual. Response.End finaliza la ejecución de la página y llama al Thread.Abort método. El Thread.Abort método hace que aparezca el mensaje de ThreadAbortException error.

Solución alternativa

Para solucionar este problema, úselo Server.Execute en lugar de en el método de Server.Transfer ProcessRequest HTTPHandler . El método ProcessRequest modificado es el siguiente:

Visual C# código de ejemplo de .NET

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 de ejemplo .NET

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

Estado

Este comportamiento es una característica del diseño de la aplicación.

Pasos para reproducir el comportamiento

  1. En Microsoft Visual Studio .NET, use Visual Basic .NET o Visual C# .NET para crear un nuevo proyecto ASP.NET aplicación web. De forma predeterminada, se crea WebForm1.aspx. Asigne al proyecto el nombre ServerTransferTest.

  2. Haga clic con el botón secundario en WebForm1.aspx y, a continuación, seleccione Ver origen HTML.

  3. Reemplace el código existente por el siguiente código de ejemplo:

    <%@ 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. Haga doble clic en Vista de diseño de WebForm1.aspx y, a continuación, reemplace el código de salida en la página de código subyacente por el siguiente código de ejemplo:

    Visual C# código de ejemplo de .NET

    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 de ejemplo .NET

    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. En el menú Archivo, seleccione Agregar nuevo elemento.

  6. En Agregar nuevo elemento, seleccione Clase. En el cuadro de texto Nombre en Agregar nuevo elemento, cambie el nombre de la clase y, a continuación, haga clic HelloWorldHandler en Abrir.

  7. Reemplace el código existente en el archivo HelloWorldHandler de clase por el siguiente código de ejemplo:

    Visual C# código de ejemplo de .NET

    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 de ejemplo .NET

    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. Repita los pasos 5 y 6 para agregar otro archivo de clase. Cambie el nombre del archivo de clase HelloWorldHandlerFactory .

  9. Reemplace el código existente en el archivo HelloWorldHandlerFactory de clase por el siguiente código de ejemplo:

    Visual C# código de ejemplo de .NET

    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 de ejemplo .NET

    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. Abra el Web.config archivo y, a continuación, agregue la <httpHandlers> sección en la sección de la siguiente <system.web> manera:

    <configuration>
        <system.web>
            <httpHandlers>
                <add verb="*" path="*.ashx" type="ServerTransferTest.HelloWorldHandlerFactory,ServerTransferTest" />
            </httpHandlers>
        .....
        </system.web>
    </configuration>
    
  11. En el menú Depurar, seleccione Inicio y, a continuación, haga clic en el siguiente hipervínculo en WebForm1.aspx:
    http://localhost/ServerTransferTest/test.ashx

Referencias