When triggering file downloads (e.g., Excel exports) from controls inside an UpdatePanel, standard asynchronous postbacks fail because the response stream cannot be modified mid-async request. The solution is to force a full postback for the download button using PostBackTrigger.
1. Configure PostBackTrigger in ASPX
Place the <Triggers> section inside the <asp:UpdatePanel>, but outside the <ContentTemplate>:
<asp:UpdatePanel ID="upMain" runat="server">
<ContentTemplate>
<asp:Button ID="btnExport" runat="server" Text="Export to Excel" OnClick="btnExport_Click" />
<!-- other controls -->
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnExport" />
</Triggers>
</asp:UpdatePanel>
2. Server-Side Export Logic
In the button click handler, generate the Excel file and deliver it via HTTP response:
protected void btnExport_Click(object sender, EventArgs e)
{
// Ensure ScriptManager recognizes this as a full postback
ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(btnExport);
DataTable data = GetDataForExport(); // your data source
// Generate Excel using NPOI (HSSFWorkbook for .xls)
string fileName = "IPQCSearchList.xls";
string exportPath = Path.Combine(Server.MapPath("~/Excel"), fileName);
// Ensure directory exists
Directory.CreateDirectory(Path.GetDirectoryName(exportPath));
using (var fs = new FileStream(exportPath, FileMode.Create, FileAccess.Write))
{
IWorkbook workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Sheet0");
// Write header row
IRow headerRow = sheet.CreateRow(0);
for (int col = 0; col < data.Columns.Count; col++)
{
ICell cell = headerRow.CreateCell(col);
cell.SetCellValue(data.Columns[col].ColumnName);
}
// Write data rows
for (int i = 0; i < data.Rows.Count; i++)
{
IRow dataRow = sheet.CreateRow(i + 1);
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = dataRow.CreateCell(j);
object value = data.Rows[i][j];
cell.SetCellValue(value == null ? string.Empty : value.ToString());
}
}
workbook.Write(fs);
}
// Stream file to client
FileInfo fileInfo = new FileInfo(exportPath);
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", $"attachment; filename={Server.UrlEncode(fileName)}");
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.TransmitFile(fileInfo.FullName);
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
3. Key Notes
PostBackTriggerbypassses partial rendering — essential for resopnse manipulation.ScriptManager.RegisterPostBackControl()ensures the ScriptManager doesn’t treat the button as async.- Use
Response.TransmitFile()instead ofResponse.WriteFile()orBinaryWrite()for large files and reliability. - Always call
CompleteRequest()instead ofResponse.End()to avoid thread-abort exceptions. - Set proper
Content-TypeandContent-Dispositionheaders to handle filename encoding and browser behavior.