I implemented the AsyncFileUpload
control on a web page. This web page requires uploaded files to appear in a GridView
.
The GridView
contains the following columns: "File Name", "Confidential" Check Box, and a "Remove" button to remove the uploaded file.
Since the AsyncFileUpload
postback does not do a full page postback, I need to "force" a postback on the OnClientUploadComplete
event of the AsyncFileUpload control in order to render the gridview after uploading a file.
In the OnClientUploadCompleteEvent
, I use javascript to call __doPostBack
. In this postback, I only bind my GridView and display the file information (I don’t re-save the file).
The problem: On the AsyncFileUpload
’s first “partial” postback, the file is successfully uploaded, as expected. On the second postback that I force with __doPostBack
, the file is re-uploaded.
You can verify this by using Google Chrome, which displays the upload progress. The behaviour is as follows:
- After selecting the file, the progress increments from 0% to 100% and the file is uploaded.
- After this, the __doPostBack
executes, and you can see the upload progress increment again from 0% to 100%.
How can I make sure the Gridview is properly populated, but that the file is not uploaded twice?
I attached a sample solution which contains the issue: https://www.yousendit.com/download/MzZFc2ZBNDRrYUN4dnc9PQ
Maybe ugly, but works:
1)
Add a css-hidden asp:Button bellow the asp:AsyncFileUpload AsyncFileUpload1
control.
<asp:Button runat="server" ID="btnClick" Text="Update grid" style="display:none"/>
2)
On the Page_Load
method, remove the if (Request.Params.Get("__EVENTTARGET") == "UploadPostback")
and put its block in a simple else
to the previous if
.
3)
On the AsyncFileUpload1_UploadedComplete
function, also remove the if (Request.Params.Get("__EVENTTARGET") != "UploadPostback")
line, but leave intact everything that was inside it.
4)
Back to the aspx. Put a asp:UpdatePanel outside the grid GridView1.
<asp:UpdatePanel runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnClick" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView ID="GridView1" ...
YOUR GRID CODE REMAINS THE SAME
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
5)
The last step is to change the AjaxUploadComplete
client-side javascript function to make it trigger the postback.
Replace it with the following:
function AjaxUploadComplete() {
var btnClick = document.getElementById("btnClick");
btnClick.click();
}
Any file the user selects is uploaded only once.
All changes here are meant to be made in AjaxUpload.aspx & AjaxUpload.aspx.cs of your AjaxUpload.zip.
There is a simpler solution
@@t0x1n3Himself the solution u gave is very simple but does not work
surround the AsyncFileUpload with an update panel name it UpdatePanelAFU
then in the UpdatePanelAFU do as the following :
protected void AsyncFileUpload_UpdatePanelAFU(object sender,AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
if (Request.Params.Get("__EVENTTARGET") != "UpdatePanelAFU")
return;
..... rest of the code
}
enjoy!
I believe @Veera had it right. UploadComplete was being called multiple times as the file was uploading. The following worked for me.
void AsyncFileUpload1_UploadedComplete(object sender, AsyncFileUploadEventArgs e) {
if (AsyncFileUpload1.IsUploading) return;
// rest of your upload code
}
I don't have access to your sample solution which contains the issue but i encounter a double postback too in my project with the AsyncFileUpload component.
I found a very simple workaround :
Just add:
private bool justUploaded = false;
Then:
void AsyncFileUpload1_UploadedComplete(object sender, AsyncFileUploadEventArgs e)
{
if (justUploaded) return;
justUploaded = true;
// rest of your upload code
}
I find this a more elegant solution, found here: http://forums.asp.net/t/1951566.aspx?AsyncFileUpload+uploads+twice) but below is my altered fully working code:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>AsyncFileUpload Example</title>
<script type = "text/javascript">
function uploadComplete(sender) {
$get("<%=lblMesg.ClientID%>").innerHTML = "File Uploaded Successfully";
clearContents();
}
function uploadError(sender) {
$get("<%=lblMesg.ClientID%>").innerHTML = "File upload failed.";
clearContents();
}
function clearContents() {
var span = $get("<%=AsyncFileUpload1.ClientID%>");
var txts = span.getElementsByTagName("input");
for (var i = 0; i < txts.length; i++) {
if (txts[i].type == "text") {
txts[i].value = "";
}
if (txts[i].type == "file") {
txts[i].value = "";
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<cc1:AsyncFileUpload OnClientUploadError="uploadError"
OnClientUploadComplete="uploadComplete" runat="server"
ID="AsyncFileUpload1" Width="400px" UploaderStyle="Modern" EnableViewState = "false"
UploadingBackColor="#CCFFFF" ThrobberID="imgLoader" OnUploadedComplete = "FileUploadComplete"
/>
<asp:Image ID="imgLoader" runat="server" ImageUrl = "~/images/loader.gif" />
<br />
<asp:Label ID="lblMesg" runat="server" Text=""></asp:Label>
</form>
</body>
</html>
AsyncFileUpload
has a property that named IsUploading
.
when this property is set to false, a postback
will happen.
you can check this property like this:
if(AsyncFileUpload1.IsUploading)
{
..... upload codes
}