Wednesday, June 25, 2014

SharePoint 2013 - how to move files and folders with versions programmatically

This is a demonstration how you can copy files, folders and Document Set programmatically. 

If you want to move just files (documents) inside same SharePoint site and keep all versions of that file, an example is shown in the method MoveFileWithVersions.

If you have folders that contain multiple files and you want to move one folder with all files that are contained in that folder and all versions of files, then look at method MoveFolderWithVersions.

But, if you have Document Set (and files inside) and you want to copy it to a different location and keep all versions of these files, it is not possible. You can copy Document Set with all files inside, but you cannot copy versions of these files, you will get only last versions of documents. This is method CopyDocumentSet.

In first two methods (MoveFileWithVersions and MoveFolderWithVersions) you actually move files and folders to a new location, you do not copy it - file (or folder) is only on the new location, but in the last method (CopyDocumentSet), you just copy Document Set - you get same Document Set on new and old location (but on the new location there is only one version of files).

If you want to move Document Set and its files with versions to a new location, you can do that if you recreate same Document Set on the new location and copy each individual file from that Document Set with MoveFileWithVersions method.

Here is the code created in simple Console Application:

static void Main(string[] args)
     using (SPSite site = new SPSite("http://dev/sites/test"))
          using (SPWeb web = site.OpenWeb())
               SPList oldLib = web.Lists["sourceDocLib"];
               SPList newLib = web.Lists["destinationDocLib"];
               // move file with all versions
               MoveFileWithVersions(oldLib, newLib);

               // move folder with its files and their versions
               MoveFolderWithVersions(web, oldLib, newLib);
               // copy Document Set - DOES NOT INCLUDE OLD VERSIONS OF THE FILES
               CopyDocumentSet(web, oldLib, newLib);

private static void MoveFileWithVersions(SPList oldLib, SPList newLib)
     SPListItem item = oldLib.GetItemById(1); 
     SPFile file = item.File;
     file.MoveTo(newLib.RootFolder.Url + "/" + item.File.Name, true);

private static void MoveFolderWithVersions(SPWeb web, SPList oldLib, SPList newLib)
     SPFolder oldFolder = web.GetFolder(oldLib.RootFolder.Url + "/myFolder");
     oldFolder.MoveTo(newLib.RootFolder.Url + "/myFolder");

private static void CopyDocumentSet(SPWeb web, SPList oldLib, SPList newLib)
     SPFolder oldFolder = web.GetFolder(oldLib.RootFolder.Url + "/myDS");
     DocumentSet documentSet = DocumentSet.GetDocumentSet(oldFolder);
     SPContentTypeId contentTypeId = newLib.ContentTypes["Document Set"].Id;
     byte[] documentSetData = documentSet.Export();
     string documentSetName = documentSet.Item.Name;
     SPFolder targetFolder = newLib.RootFolder;
     Hashtable properties = oldFolder.Properties;
     DocumentSet.Import(documentSetData, documentSetName, targetFolder, contentTypeId, properties, web.CurrentUser);

Tuesday, June 10, 2014

SharePoint 2013 workflow debug

There are many posts on the web regarding SharePoint 2013 workflow debugging. Almost all of them recommend using TestServiceHost.exe; first enabling inbound rule for this service, then starting it and attaching to it from Visual Studio (or starting debug with F5). I tried this approach but with no success, breakpoint simply wasn't hit.

So, I tried different approach, and it is also much easier procedure:

NOTE: I have Workflow manger installed on the same machine as SharePoint 2013.
1. Open Visual Studio and open project with your workflow and deploy your workflow (if it isn't already deployed).

2. Check that debug option is enabled;
Right mouse click on your project and click on "Properties". Click on tab "SharePoint" and check if option "Enable Workflow debugging" is selected.

If it isn't, select it and redeploy solution.

3. Set breakpoint in your workflow;
Right mouse click on activity and click on "Breakpoint --> "Insert breakpoint".

4. In Visual Studio click on "Debug" --> "Attach to process"

Select "Microsoft.Workflow.ServiceHost.exe"

Click on "Select" button on the same screen

On the new screen select option "Debug these code types" and select "Workflow"

Click "OK" button and then "Attach" button.

5. Now you are all set, and if you run your workflow, your breakpoint should be hit like shown on the last image.