Exportar a Excel - ThreadAbortException
-
29-10-2019 - |
Pregunta
Tengo un problema con la conversión al código de Excel que estoy encontrando. Estoy trabajando en un proyecto de sitio web en .NET 4.0, y he creado una clase para esto que hace lo siguiente (basado en http://mattberseth.com/blog/2007/04/export_gridview_to_excel_1.html ):
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition",
string.Format("attachment; filename={0}", fileName)); HttpContext.Current.Response.ContentType = "application/ms-excel"; using (StringWriter sw = new StringWriter()) {
using (HtmlTextWriter htw = new HtmlTextWriter(sw)) {
//Create a table to contain the grid
//Add header row
//Add each data row
//Add Footer row
//Render the table into the htmlwriter
// render the htmlwriter into the response
HttpContext.Current.Response.Write(sw.ToString());
HttpContext.Current.Response.End();
}
}
Llamo a esta clase desde un control de usuario que contiene un botón que se agrega a un GridView que se muestra en la página. Esto funciona como se esperaba: haga clic en el botón, se le presentará una opción de descarga para abrir o guardar la hoja de cálculo de Excel resultante que contiene los datos de GridView.
Sin embargo, cuando llamo a esto desde un botón de enlace dentro de un GridView diferente, me gustaría construir una vista de cuadrícula dinámica para contener datos y exportarlos. Cuando hago eso, obtengo una ThreadAbortException de la llamada Response.End en la clase.
Pregunta 1: ¿Por qué no obtengo esa excepción ThreadAbortException cuando llamo al mismo código desde un control de usuario? ¿Los controles de usuario obtienen sus propios hilos o algún otro tipo de contexto?
La búsqueda del error que obtengo cuando se produce la excepción ThreadAbortException me llevó a intentar reemplazarla con ApplicationInstance.CompleteRequest (). Cuando hago eso, ya no obtengo la ThreadAbortException, pero esto rompe el control de usuario que funcionaba anteriormente; en lugar de la hoja de cálculo de Excel resultante que contiene los datos de la cuadrícula, contiene el HTML de la página que lo contiene y, en cualquier caso, es bastante fácil de suprimir ese error con una captura vacía. Sin embargo, no corrige la llamada directa con GridView generado dinámicamente, ese código genera un error de JavaScript: "El mensaje recibido del servidor no se pudo analizar".
Me encantaría saber qué está pasando aquí exactamente, pero estoy en el punto de necesitar resultados independientemente de la comprensión. Todos los demás enfoques que he probado (cuadrícula de datos en lugar de GridView, etc.) tienen los mismos problemas y son esencialmente los mismos cuando se trata de "hacerse cargo" la respuesta actual y el uso de stringwriter y htmlwriter para convertir los datos en una respuesta con excel contentType. Y dado que esto funciona de manera demostrable en el contexto de un control de usuario, estoy al final de mi ingenio en cuanto a por qué no funcionará cuando se llame directamente ...
Solución 3
En realidad, el problema no tenía nada que ver con la exportación de Excel.El error "... no se pudo analizar" fue la clave.De estos enlaces obtuve la clave, que era que los eventos de la cuadrícula solo causan un evento de devolución de datos parcial:
http://forums.asp.net/t/1392827.aspx
Esto explica la excepción ThreadAbortException y el error "... no se pudo analizar".Agregar esto al OnPreRender del ImageButton fue la solución:
protected void addTrigger_PreRender(object sender, EventArgs e)
{
if (sender is ImageButton)
{
ImageButton imgBtn = (ImageButton)sender;
ScriptManager ScriptMgr = (ScriptManager)this.FindControl("ScriptManager1");
ScriptMgr.RegisterPostBackControl(ImgBtn);
}
}
Otros consejos
Prueba en su lugar: HttpApplication.CompleteRequest () según: http://www.c6software.com/codesolutions/dotnet/threadabortexception.aspx
Hablan del html adicional que se muestra
usa esto
Response.Clear()
Response.AddHeader("content-disposition", atchment;filename=fm_specification.xls")
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = "application/vnd.xls"
Dim stringWrite As System.IO.StringWriter = New System.IO.StringWriter
Dim htmlwrite As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(stringWrite)
GridView1.RenderControl(htmlwrite)
Response.Write(stringWrite.ToString)
Response.End()
en lugar de gridview1 puede usar div
dont forget to add this on your page
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
End Sub
El evento en el que se llama al código Export to Excel, debe realizar una devolución de datos completa.el problema se debe a que solo realiza una devolución de datos parcial.
Tuve el mismo error y se resolvió cuando hice una devolución de datos completa.
Espero que esto ayude a alguien.