ViewIt is likely that DropBox has changed the game field or at least the desired and expectations of what the conventional FTPs had to offer. It is hard to envision a storage service now a days without a syncing utility. Those services that lacked such an alternative ended up playing catch up and adapting.

This might change in a very near feature but yet there is a minuscule community that hesitates to lever the power of the browser entirely. Today we count with Google Docs, Office 365, and even Office Online, to name a few, and yet our desire to remain completely functional on the cloud is at times not present.

I had an exposure to this social experiment, when a few known stakeholders who happen to be SharePoint users insisted on working on their documents – Document Libraries - outside the browser and thus outside the IE ActiveX object realm.

Thankfully, SharePoint 2013 introduced OneDrive which possess a great Synchronization feature. Yet, It leave SharePoint 2010 Farm users salivating over similar Synchronization tools. For 2010 application, Third Party Synchronization tools are really expensive and at times complex. Since Free is always better. I embarked in the task of creating a Sync tool for 2010 Farm Users.

Initial Concept

Usually more control is needed when dealing with SharePoint Documents in a document library. In my scenario I empower users to commit changes to the SharePoint Server, but also to extract changes per their request. User usually do not want their working copy to be overwritten unless they wish to.

Thus, in the original idea, the application is to perform two key actions



The above scenario requires to keep track of the changes made local and compare them with the changes in the SharePoint Server. The application will then define if there are changes pending either from the update or the commit action.

The How – Getting Document Library Changes

Here we have arrived to the section of my blog where I share some of my thoughts on how I brought this to fruition. The Microsoft.SharePoint.Client library enable us to access many element of the SharePoint Object Model. Among this elements, Document libraries is one of them.

For Simplicity Purposes and easy access, this is how I make the SharePoint Client Context accessible to my entire class. I has initialized pass the User, Password, Domain to the constructor.

   1: private ClientContext _context = null;
   2:         private ClientContext Context
   3:         {
   4:             get
   5:             {
   6:                 if (_context == null)
   7:                 {
   8:                     _context = new ClientContext(_url);
   9:                     _context.Credentials = new NetworkCredential(_username, _password, _userdomain);
  10:                     return _context;
  11:                 }
  12:                 else
  13:                 {
  14:                     return _context;
  15:                 }
  16:             }
  17:         }

Subsequently I process to execute a query against the context in order to verify that I am good to proceed in executing request for SharePoint Objects.

   1: public bool Authorized
   2:         {
   3:             get
   4:             {
   5:                 try
   6:                 {
   7:                    Context.ExecuteQuery();
   8:                     return true;
   9:                 }
  10:                 catch(Exception ex)
  11:                 {
  12:                     return false;
  13:                 }
  14:             }
  16:         }


In the traditional sense we request document libraries files by executing load commands against the Context, However, In my experience the information provided from the file under the FileCollection is very limited.

   1: FileCollection files = folder.Files;
   2: Context.Load(files);
   3: Context.ExecuteQuery();

In order to retrieve a lot more information about the file / files we rather query context against List Collection Item, this object then provides a more comprehensive information about a document under the FieldValues Dictionary

   1: private IEnumerable<ListItem> RetrieveFiles(string DocumentLibrary)
   2: {
   3:     List list = Context.Web.Lists.GetByTitle(DocumentLibrary);
   4:     CamlQuery query = new CamlQuery();
   5:     query.ViewXml = "<View Scope='RecursiveAll'></View>";
   6:     ListItemCollection listItems = list.GetItems(query);
   8:     Context.Load(listItems);
   9:     Context.ExecuteQuery();
  10:     var collection = listItems.AsEnumerable<ListItem>();
  11:     return collection;
  13: }


The above method provided us all the list of files and folders in one list. This list is very relevant; yet we need a way to organize our file structure better. the intent is to arrange it this way in our syncing folder. For this we will need a recursive method that will organize our files into folder and subfolders.

   1: public List<SPFolder> LoadLibraryFiles(string DocumentLibrary)
   2: {
   3:     Folder folder = Context.Web.GetFolderByServerRelativeUrl(@"/" + DocumentLibrary + @"/");
   4:     Context.Load(folder);
   5:     Context.ExecuteQuery();
   6:     return  RetrieveFolderDocuments(folder, RetrieveFiles(DocumentLibrary));
   7: }
   1: private List<SPFolder> RetrieveFolderDocuments(Folder folder, IEnumerable<ListItem> itemsInfo)
   2: {
   3:     List<SPFolder> spfolders = new List<SPFolder>();
   5:     FileCollection files = folder.Files;
   6:     Context.Load(files);
   8:     FolderCollection folders = folder.Folders;
   9:     Context.Load(folders);
  10:     Context.ExecuteQuery();
  12:     SPFolder spfolder = new SPFolder();
  13:     spfolder.FolderName = folder.Name;
  14:     spfolder.ServerPath = itemsInfo.Where(x => x.FieldValues["FileRef"].ToString() == folder.ServerRelativeUrl)
  15:         .Select(g => g.FieldValues["FileRef"].ToString()).FirstOrDefault();
  16:     var filelist= files.AsEnumerable<File>();
  18:     spfolder.Files = itemsInfo.Join(files.AsEnumerable<File>(), info => info.FieldValues["FileRef"].ToString(), f => f.ServerRelativeUrl,
  19:         (info, f) => new SPDocument
  20:         {
  21:             FileName = f.Name,
  22:             ServerPath = info.FieldValues["FileRef"].ToString(),
  23:             CreatedDate = Convert.ToDateTime(info.FieldValues["Created"].ToString()),
  24:             LastModify = Convert.ToDateTime(info.FieldValues["Last_x0020_Modified"].ToString()),
  25:             ModifyBy = info.FieldValues["Modified_x0020_By"].ToString()
  26:         }).ToList<SPDocument>();
  27:     spfolder.Folders = new List<SPFolder>();
  29:     foreach (var childfolder in folders.AsEnumerable<Folder>().Where(x => x.Name != "Forms"))
  30:     {
  31:         spfolder.Folders.AddRange(RetrieveFolderDocuments(childfolder, itemsInfo));
  33:     }
  34:     spfolders.Add(spfolder);
  36:     return spfolders;
  37: }

The Model

   1: public class SPFolder
   2:     {
   3:         public string FolderName { get; set; }
   4:         public string ServerPath { get; set; }
   6:         public List<SPFolder> Folders { get; set; }
   7:         public List<SPDocument> Files { get; set; }
   8:     }
  10:     public class SPDocument
  11:     {
  12:         public string FileName { get; set; }
  13:         public string ServerPath { get; set; }
  14:         public string ModifyBy { get; set; }
  15:         public DateTime CreatedDate { get; set; }
  16:         public DateTime LastModify { get; set; }
  19:     }

The Result


The Application

The application was developed in WPF and provides a Wizard utility in order to sync new Document Libraries to a local folder. The application also runs in the background to enable individual commit of files to the server and updates of specific files. The user could update or commit the whole document library, or simple folders located under the document library.

The application list the sync folders in the below window


The UI

The UI provides a way for the user to enter  the SharePoint site along with its credentials. A validation process takes place in order to verify that user rights allow to query Document Library elements against the context

ViewUrlEntry ViewCredentialsEntry ViewLibrarySelect ViewDownloadCompleted ViewPulledFiles

The Overlay

As explained the application also consist of an overlay that allows the update of individual folders or documents.


Installing the Application

Unzip the SPZYNC Folder and Extract the Files in Any Folder of your choosing
Open as an Administrator the File under the name of Installer.exe then hit i to register the overlay
You could verify that the overlay has been properly installed, by running regedit and verifying that the following items appear in the registry
Open the program under the name SPSync2.exe


Preview Sync Functionality Preview Overlay Functionality