SharePoint Drag/Drop file upload using the ASP.NET AJAX Control Toolkit

In my current work on a custom interface for a document management system, I was challenged to create a drag/drop interface for adding files to SharePoint. 

I investigated a number of alternatives. Initially these were my considerations:

  • Not all browsers (most notably IE9) do not support HTML5, which natively supports drag/drop.  
  • Even if HTML5 is supported, there’s still quite a bit of wiring to do in Javascript. 
  • As developers, we try not to recreate the wheel.  If a problem has already been solved, it’s usually a better alternative to use that – at least as a starting point.

As it turns out, there’s no shortage of drag/drop solutions out there.  But try one that applies to SharePoint, provides compatibility with non HTML5 browsers, shows a progress bar, etc.   In the end I decided to try the ASP.NET AJAX Control Toolkit.

Getting started

On the surface, installation is straightforward for anyone who is familiar with ASP.NET development.  Add an entry to the web.config, drop the appropriate DLL in the GAC, and that’s pretty much it.  However, (ahem) we’re using SharePoint here, which brings up a couple of issues that we’ll need to address.   Fortunately I’ve already hammered out these issues, so you don’t have to.

Issue 1:  Version

We need to use the .NET 3.5 version.   There are two compiled versions.  We are again reminded that SharePoint 2010 doesn’t use the latest version of .NET.  

Issue 2: ScriptManager

The ScriptManager packaged with the Toolkit needs to be used, INSTEAD of the standard ASP ScriptManager which is on all master pages in SharePoint.

before:

<asp:ScriptManager id="ScriptManager" runat="server" …." />

after:

<%@ Register Assembly="AjaxControlToolkit, Version=3.5.60501.0, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>

<ajaxToolkit:ToolkitScriptManager runat="server" …. />

Issue 3: File Uploader is not ready for prime time

The drag/drop control is called AjaxFileUpload (not to be confused with AsyncFileUpload, which is also part of the toolkit).   Once you have the ScriptManager issue handles, you’ll be able to get things working using the simple demo.  However, I found (as of the 5/1/12 release) that there were a couple of bugs.

1. The control assumes that no parameters are present on the page which contains the control.  This is documented in this bug report.  I won’t go into detail on this.  Suffice it to say that it should be fixed in the future.   The impact is that the control cannot be used on most SharePoint pages including dialogs invoked using SP.UI.ModalDialog.showModalDialog() – which appends the parameter IsDlg=1 even if you don’t explicitly do so!

2. a number of features of the drag/drop uploader do not work.  For example, exceptions generated when the code is downloading are not “passed through” to the javascript event which should be fired in the event of an error.   In fact, when I delved into the code, I found that the OnClientError event is never fired!

The way I fixed this issue was to download the AjaxToolkit code and “just fix it”.  I spent a few hours learning how the code works, and modified the code itself, in C# and Javascript.   For anyone interested in following this path, you can download the changed code here (I only included the files I changed).  When you download the code, make sure to use the version targeted to .NET 3.5.  It’s a VS 2008 project, but of course it’s ok for you to convert it to VS 2010.

Finally: Hooking it up to SharePoint

The file uploader control is very clever.  It posts back to the same page it’s located on (this is the ajax part) and calls a code block that you can define using C# in your ASP or Codebehind.   Mine looks something like this:

protected void ajaxUpload1_OnUploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
        //you’ll need some logic in here to determine where to put the files. 
        string filename = string.Format("{0}/{1}", SPContext.Current.Site.Url, e.FileName); 

        using (SPWeb web = new SPSite(uploadTarget).OpenWeb()) 
        {
            web.AllowUnsafeUpdates = true;
            web.Files.Add(filename, e.GetContents(), true);
            web.AllowUnsafeUpdates = false;
        }
}

From the client interface end of things, you’ll also need to put in code to provide feedback.  There’s a good The code located here. provides a pretty good example of that; here’s another one:

//hook this up to the OnClientUploadError property of the control 

function onError(sender, e) {
//this bit of code adds an error message to a designated “errors” area. 
var test = document.getElementById("uploadErrors");
test.style.display = 'block';
var fileList = document.getElementById("fileList");
var item = document.createElement('div');
item.style.padding = '4px';
item.appendChild(createFileInfo(e));
fileList.appendChild(item);
} 

function createFileInfo(e) {
var holder = document.createElement('div');
holder.appendChild(document.createTextNode(e.get_fileName() + ': ' + e.get_errorMessage()));
return holder;
} 

//hook this up to the OnClientUploadComplete property of the control 

function onClientUploadComplete(sender, e) {
     alert("uploaded");
} 

Using this method, errors are returned to the web user.  Once our designers get through with it, it’s going to be REALLY slick!

Leave a Reply

Your email address will not be published. Required fields are marked *