Si alguna vez han utilizado un control FileUpload de .NET dentro de un UpdatePanel se habrán encontrado con que no son controles compatibles, es decir, cuando se ejecuta el evento del botón que sube el fichero te encuentras con que el PostedFile del control FileUpload es nulo.
Caso base:
<asp:UpdatePanel ID="uPnl" runat="server">
<ContentTemplate>
<asp:FileUpload ID="flUpl" runat="server"></asp:FileUpload>
<asp:Button ID="btnSubir" runat="server" Text="Subir" OnClick="btnSubir_Click"></asp:Button>
</ContentTemplate>
</asp:UpdatePanel>
Si se busca por la red se encuentran varias soluciones, la más sencilla es agregar a la lista de triggers del UpdatePanel un nuevo PostBackTrigger con el ControlId apuntando al botón de subir fichero de nuestro FileUpload (en el ejemplo anterior 'btnSubir').
<asp:UpdatePanel ID="uPnl" runat="server">
<ContentTemplate>
<asp:FileUpload ID="flUpl" runat="server"></asp:FileUpload>
<asp:Button ID="btnSubir" runat="server" Text="Subir" OnClick="btnSubir_Click"></asp:Button>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnSubir" />
</Triggers>
</asp:UpdatePanel>
Ahora bien, me encontré con el particular caso que el FileUpload se encontraba en el header de un GridView, y éste, a la vez, dentro del UpdatePanel, de la siguiente forma:
<asp:UpdatePanel ID="uPnl" runat="server">
<ContentTemplate>
<asp:GridView ID="gvw" runat="server">
<Columns>
<asp:TemplateField>
<asp:HeaderTemplate>
<asp:FileUpload ID="flUpl" runat="server"></asp:FileUpload>
<asp:Button ID="btnSubir" runat="server" Text="Subir" OnClick="btnSubir_Click"></asp:Button>
<asp:/HeaderTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnSubir" />
</Triggers>
</asp:UpdatePanel>
Al estar el control FileUpload dentro del GridView, sale el siguiente error:
A control with ID 'btnSubir' could not be found for the trigger in UpdatePanel 'uPnl'.
Esto sucede porqué se cambian los ID's dinámicamente cuando se ejecuta la página y por lo tanto el botón con ID 'btnSubir' no se llama igual.
Una vez en este punto, prové a eliminar el trigger en el UpdatePanel de la página aspx y a ponerlo dinámicamente (para poder coger el ClientID, que contiene el identificador real del control) en el evento gvw_RowDataBound de la siguiente forma:
if (e.Row.RowType == DataControlRowType.Header)
{
PostBackTrigger pt = new PostBackTrigger();
pt.ControlID = e.Row.Cells[0].FindControl("btnSubir").ClientID;
uPnl.Triggers.Add(pt);
}Igualmente, siguió saliendo el mismo error que al principio, cuando quería subir el fichero mediante el botón de añadir el FileUpload no tenía ningún fichero introducido.
Finalmente hallé la solución implementando el evento PreRender del botón que sube el fichero (en el ejemplo 'btnSubir') y utilizar el ScriptManager:
protected void btnSubir_PreRender(object sender, EventArgs e)
{
Button btn = (Button)sender;
ScriptManager newScriptManager = (ScriptManager)Page.FindControl("ScriptManager1");
newScriptManager.RegisterPostBackControl(btn);
}
Una vez implementado, cualquier botón dentro del GridView actualiza tan sólo el GridView, a excepción del botón de subida del fichero (btnSubir) del Header que hace un PostBack (necesario para que funcione el FileUpload).