Thursday, November 12, 2009

Asyncronous file upload in asp.net

I recently had a customer request a feature to upload files to their account.

It's an interesting architectural dilemma, since the file is on the client, the file is to be stored on the Server (in my case, not even the web server), and I definitely wanted to avoid postbacks since it was a rich web app and a postback would look/behave badly.

Some options are AjaxUploader, while it looks solid, I didn't want to pay for the service at the time since paperwork for this type of functionality was more work than coding from scratch.

Another option was the AsyncFileUploader which comes with the latest Microsoft Toolkit, screenshot below. It does an automatic upload on selection, and provides a mind-numbing green background on success, and a red background if it was unsuccessful (which is a nice feature!)


Unfortunately, this great control had errors with IE6. Since a lot of our users are on IE6, this is a show-stopper.

I adopted an idea from a co-worker, kludgy, but effective. Essentially, you put a file upload control in an iFrame (so a postback within the iFrame doesn't postback the entire page), then send a Javascript message from the code behind when the file upload is complete. There were several challenges with this:
  1. asp.net name mangling
  2. Lots of Javascript
  3. Updating the asp.net grid within the UpdatePanel so a full page refresh doesn't happen
Here was the result, works pretty well:

Notice that the filename can be clicked to be viewed, and the delete option, these are all done in the asp.net code behind and done without full postback since the grid is within an UpdatePanel.

So how do you update the grid on file upload?

I added a linkbutton on the grid with associated codebehind (I kept the LinkButton1 name for posterity):
  
protected void LinkButton1_Click(object sender, EventArgs e)
{
   LoadDocs();
}
Now, when the file uploads, simply call the javascript function uploadNotify, via ServerCode:
ClientScript.RegisterStartupScript(this.GetType(), "uploadNotify", script);
Now, the final step? Write the uploadNotify script on the parent page:
function raiseAsyncPostback() {
   __doPostBack("<%= this.LinkButton1.UniqueID %>", "");
}
The UniqueId is resolved to the mangled name (this nuisance now resolved in .net 4.0 - yay!)

That's what it takes! Kludgy, but effective, and gives you highly customizable options. Personally, I'd wait for the Toolkit version to be spiffed up, looks really good.

No comments: