Recently I ran into an issue, that by the looks of Google, is affecting many others too.  I wanted to be able to allow users to select an upload path, using the standard Asp.Net fileUpload control, and maintain that control’s path through postbacks, so I could perform some server side validation.  As far as I can tell, this is impossible.  It is also only possible to get the control’s path, programatically when a full postback occurs and for security reasons, the control does not allow its path to be programatically set, so storing the path prior to the postback and restoring it, is not an option either.   So what this means is there is no way to accomplish what I needed to do using the standard fileUpload control.

Recently the AjaxControlToolkit has introduced a new control, the AsyncFileUpload control. http://www.asp.net/ajax/ajaxcontroltoolkit/Samples/AsyncFileUpload/AsyncFileUpload.aspx

This control can be set up to look identical to the standard fileUpload control, but immediately performs a file upload once the user selects their file path. This allows async file uploading! Problem solved! ….. well…..sorta

I also wanted a way to disable all other asyncFileUpload controls on a page while an upload is in progress, this was preventing an “Unknown Server Error” browser alert message when trying to perform 2 async uploads at once. I google’d and google’d for this problem, and could not find anyone who was having a similar issue, or a fix for it, so I had to go for a work around.

In a nutshell, I implemented the client-side uploadStarted, and uploadCompleted events on the AsyncFileUpload control, and used some Jquery within those to disable specific controls using css classes. Problem with this was that once an AsyncFileUpload control is disabled, its file path can no longer be read server-side until the page is refreshed again.  I am not sure if this is a bug, or is by design, but never the less, it was not working properly, and time was not on my side.

So I had to develop another workaround…

I decided I could show the user a button and textbox that was rigged to look JUST like a file upload control. I could populate the textbox with the fileUpload control’s path, and they would never know the difference….hopefully.

After a long battle with the fileUpload controls, I managed to get a fairly suitable workaround…. when a file starts uploading, the “fake” file upload control appears, and when the file is done uploading, the real one comes back.

Let’s start with the code:

In the code behind you can register the script as a client script block, in the Page_Load or somewhere similar.  Wherever you prefer, just so that it is included on the rendered page. The code I used, is below.  It uses Jquery to find elements based on their css class, and to hide all AsyncFileUploads on the page once an upload starts and then bring those back when the upload is complete along with populating our “fake” fileupload with the file upload path that is used, to make it all look like its a real file upload control that is just disabled.  Confusing? It’s not too bad, it’s just hard to explain:

private void SetJavaScript()
{
    /*
        * All this Javascript basically hides/shows/populates a
        * fake file upload control (button and textbox), that is displayed when
        * a file is being uploaded
        * This lets a user only upload one file at a time, and
        * prevents errors from the AsyncFileUpload control
        * */

    ScriptManager.RegisterClientScriptBlock(this.Page,typeof(Page), "UploadJS",

        @"

            function UploadStarted(sender, args)
            {
            disableAllUploads();
            }

            function disableAllUploads()
            {
            $('.asyncFileUpload').hide();
            $('.fakeAsyncFileUpload').show();
            }

            function enableAllUploads()
            {
                $('.asyncFileUpload').show();
                $('.fakeAsyncFileUpload').hide();

                $('.asyncParent input[type=file]').each(
                    function()
                    {
                        $(this).parents('.asyncParent')
                        .find('.fakeAsyncFileUploadText').val(this.value);
                    });
            }

        function UploadComplete(sender, args)
        {
            enableAllUploads();
        }"

        , true);
}

Here is what the ASPX looks like
(this is where the CSS classes are listed, and will make sense in the context of the JavaScript above:

<asp:Panel ID="pnlFile" runat="server" Visible="false" Width="325">
    <div class="asyncParent">
        <div class="fakeAsyncFileUpload" style="display: none;">
            <asp:TextBox ID="fakeTxt" CssClass="fakeAsyncFileUploadText" Width="207"
            runat="server"
                Enabled="false" />
            <asp:Button ID="fakeBtn" runat="server" Enabled="false" Text="Browse" />
            <asp:Image ID="throbberImg" runat="server" ImageUrl="~/images/indicator.gif"
            Style="position: relative;
                left: 2px; top: 4px;" />
        </div>
        <ajaxtoolkit:asyncfileupload id="btnFileUpload" cssclass="asyncFileUpload"
            onclientuploadcomplete="UploadComplete" onclientuploadstarted="UploadStarted"
            persistfile="true" runat="server" width="280" errorbackcolor="White"
            throbberid="throbberImg"
            completebackcolor="White" />
    </div>
</asp:Panel>

As you can see, each control has its own style for a purpose. That way they can easily be hidden/shown using Jquery
and client-side events of the AsyncFileUpload control.

This was my workaround to the whole “fileUpload control clearing on postback issue. Hopefully it can benefit others who were having the same problem I was.