Compartir a través de


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

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

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

Síntomas

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

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

Causa

Cuando se llama a , ASP.NET llama Server.Transferinternamente al Server.Execute método para transferir el control y llama al Response.End método para finalizar el procesamiento de la página 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 ThreadAbortException mensaje de error.

Solución alternativa

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

  • Código de ejemplo de 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());
        }
    }
    
  • Código de ejemplo de 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
    

Status

Este comportamiento es por diseño.

Pasos para reproducir el comportamiento

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

  2. Haga clic con el botón derecho en WebForm1.aspx y seleccione Ver origen HTML.

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

    <%@ 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 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 código de ejemplo siguiente:

    • Código de ejemplo de 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
         }
      }
      
    • Código de ejemplo de 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. 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 HelloWorldHandlery, a continuación, seleccione Abrir.

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

    • Código de ejemplo de 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; }
             }
          }
      }
      
    • Código de ejemplo de 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. Repita los pasos 5 y 6 para agregar otro archivo de clase. Cambie el nombre del archivo HelloWorldHandlerFactoryde clase .

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

    • Código de ejemplo de 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 )
             {
             }
          }
      }
      
    • Código de ejemplo de 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. Abra el archivo web.config y agregue la <httpHandlers> sección en la sección de la <system.web> siguiente 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, seleccione el siguiente hipervínculo en WebForm1.aspx:

    http://localhost/ServerTransferTest/test.ashx

Referencias