Using Telerik RadUpload Control with SharePoint Document Libraries Silverlight

Having examined the RadUpload control now from the ASP.NET perspective in this post, it is time to investigate the other platform of interest, Silverlight. This is a little bit trickier then working with the ASP.NET port of the control since it requires developing a HTTP handler to manage the upload, and, constructing the stream to push into SharePoint requires a temporary location on the server to host the file pre-upload operation into the SharePoint Document Library. So essentially, the file goes from client, to physically on the server, then to SharePoint, with subsequent removal of the file physically off the server. I was not able to build a direct stream successfully without problems, but would be interested if others have explored this route.

From the Silverlight perspective, the handler needs to be explicitly specified when invoking the RadUpload object. In general, the URL itself is constructed ala a configuration value in order to ease environment transitions in a normal ALM cycle. I am going to use a URI object since I am interested in a replacement token to a common WCF directory that contains my ASHX file and I only want the host value. This is useful if you are using the variable throughout the software.

As you can see, we are setting the RadUpload.UploadServiceUrl property to my custom handler path. Now, onto the handler itself! The part to pay close attention to is that I am also demonstrating passing a dynamic parameter to hydrate the SharePoint Document Library SPFile with metadata.

public override void ProcessStream()
{
base.ProcessStream();
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFile file = Request.Files[i];
string fileName = GetFileName();
string fullPath = string.Format("{0}\\_wcf\\TempFiles\\", HttpContext.Current.Server.MapPath(HttpContext.Current.Request.ApplicationPath));
string filename = fullPath + Path.GetFileName(file.FileName);
string path = fullPath + fileName;
if (file.ContentLength != 0)
{
file.SaveAs(filename);
string requestUrl = WebConfigurationManager.AppSettings["RootSite"];
FileStream stream = new FileStream(filename, FileMode.Open);
SPSite site = new SPSite(requestUrl);
using (SPSite elevatedSite = new SPSite(requestUrl, site.SystemAccount.UserToken))
{
using (SPWeb web = elevatedSite.OpenWeb())
{
Hashtable hashtable = new Hashtable();
hashtable.Add("Param", MyParam);
Hashtable properties = hashtable;
web.AllowUnsafeUpdates = true;
SPDocumentLibrary library = (SPDocumentLibrary) web.Lists["Document Library"];
SPFolder rootFolder = library.RootFolder;
rootFolder.Files.Add(string.Format("{0}/{1}", rootFolder.Url, fileName), stream, properties, true);
stream.Close();
}
}
File.Delete(path);
File.Delete(filename);
}
}
}
}
}
[/csharp]
The two overridden methods, SaveChunkData and ProcessStream basically are there because the handler manages the upload stream in variable size chunks. That’s the behavior you want to override. First thing we are doing is hydrating the class level parameter field so that we can have it available later when we want to push it into a HashTable for metadata support on the SPFile object. Within the ProcessSteam method where the meat of the application resides, we are getting all the posted files in the control since it support a mutable amount, and moving them onto the server. Subsequently when the file is constructed on the server, we are going to make it a stream and throw it into the RootFolder of the SPDocumentLibrary. Simple in theory, a pain in the ass to figure out!