In this blog I wanted to describe how documents can be migrated from MOSS 2007 to SharePoint 2010 environment by building a custom utility. I have used Web Services provided by SharePoint to copy number of documents from MOSS 2007 Document Library to SharePoint 2010 Document Library using SharePoint web services.
SharePoint web services
SharePoint provides us a list of web services for individual operations, we are going to use only two of them:
1. Lists.asmx(Web service reference: http://<site>/_vti_bin/Lists.asmx)
2. Copy.asmx (Web service reference: http://<site>/_vti_bin /Copy.asmx)
Let’s take a deeper look into these web methods of these web services:
From Lists.asmx web service we will use two web methods:
Lists.GetList () web method:
Method Signature:
public XmlNode GetList (string listName): Returns a schema for the specified list.
Lists.GetListItems () web method:
Method Signature:
public XmlNode GetListItems ( string listName, string viewName, XmlNode query, XmlNode viewFields,string rowLimit, XmlNode queryOptions, string webID) : Returns information about items in the list based on the specified CAML query.
From Copy.asmx web service we will also use two web methods:
Copy.GetItem() web method:
Method Signature:
public uint GetItem(string Url, out FieldInformation[] Fields,
out byte[] Stream) : Returns a Byte array representation of a document that can be passed to the CopyIntoItems method to copy the document to a different server.
Copy.CopyIntoItems() web method:
Method Signature:
public uint CopyIntoItems( string SourceUrl, string[] DestinationUrls, FieldInformation[] Fields, byte[] Stream,
out CopyResult[] Results): Copies a document represented by a Byte array to one or more locations on a server.
Programming
We can achieve our goal using any of the project types (Console Application, Windows Application, Web Application, Web services etc.). A Windows application has been created into SharePoint 2010 Development Environment, two web references (Lists.asmx & Copy.asmx) of MOSS 2007 has been added into my project. Finally our programming part given below:
1. An object of each of the proxy classes which were generated after adding the web references has been created.
2. Next the Lists.GetList() web method has been called to get the listId from SP2007 Doc Lib
Input Parameter: Name of the List (For e.g. “Shared Documents”)
Output: A xml node from which we can get the ListId and WebId
3. Then the Lists.GetListItem() web method has been called to get the Url of Individual documents from SP2007 List.
Input Parameters:
listName: Pass the ListId we got from Lists .GetList() web method.
viewName: If you want to use any view of SP2007 Doc Lib then specify the view name or pass NULL.
Query: CAML query that determines which records are returned and in what order.
viewFields: Specifies which fields to return in the query and in what order (eg. <FieldRef Name=’EncodedAbsUrl’ />).
rowLimit: specifies the number of items, or rows, to display on a page before paging begins (eg. 50 or 500).
queryOptions: An XML fragment in the following form that contains separate nodes for the various properties of the SPQuery object.
webID: Pass the webID we got from Lists .GetList() web method.
Output: A XML node from which we can get the list of URLs of each documents of SP2007 doc lib.
4. Then the Copy.GetItem() web method has been called to get the individual document from SP2007 Doc lib
Input Parameters:
Url : Pass the individual document URL from a list of URLs that we got from Lists .GetListItem() web method
Output:
FieldInformation Array: which contains the metadata information of the document that we get from SP2007 doc lib.
Byte Array : Which contains the entire document as an array of bytes (that is a base-64 representation of the retrieved document’s binary data)
5. Next the web reference URL of the object of Copy.asmx web service has been replaced from Sp2007 to SP2010. Because we are pulling the documents from SP2007 document Library but copying into SP2010 doc lib.
6. Then the Copy.CopyIntoItems() web method has been called to copy the items that we got into byte array into SP2010 document library.
Input Parameters:
SourceUrl: Pass the individual document URL from a list of URLs that we got from Lists .GetListItem() web method
DestinationUrls: Pass the destination URL of SP2010 document library.
Fields: Pass the FieldInformationArray that we got from Copy.GetItem() web method.
Stream: Pass the byte array that we got from Copy.GetItem() web method.
Output:
Results: Finally we will get a <Success> message if the document moved successfully.
The following Configuration used:
C# Code snippet Used:
To get the list of URLs from MOSS 2007 Document Library :
public List<string> GetListofUrl() { List<string> SiteUrlList = new List<string>(); NetworkCredential custCred = new NetworkCredential(ConfigurationManager.AppSettings["SP2007user"], ConfigurationManager.AppSettings["SP2007pwd"], ConfigurationManager.AppSettings["SP2007domain"]); SPListServices2010.Lists listService = new SPListServices2010.Lists(); listService.PreAuthenticate = true; listService.Credentials = custCred; listService.Url = ConfigurationManager.AppSettings["SrcWebservcUrl"] + "_vti_bin/Lists.asmx"; XmlNode list = listService.GetList(ConfigurationManager.AppSettings["SrcRootFolder"]); System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument(); string listName = list.Attributes["ID"].Value; string webID = list.Attributes["WebId"].Value; string rowLimit = ConfigurationManager.AppSettings["ListRowLimit"]; XmlDocument doc = new XmlDocument(); XmlElement query = doc.CreateElement("Query"); XmlElement viewFields = xmlDoc.CreateElement("ViewFields"); query.InnerXml = @"<OrderBy><FieldRef Name='Title' Ascending='False'/></OrderBy> "; viewFields.InnerXml = "<FieldRef Name='EncodedAbsUrl' />"; XmlNode positionNext = null; XmlNode queryOptions = doc.CreateElement("QueryOptions"); queryOptions.InnerXml = "<IncludeMandatoryColumns>False</IncludeMandatoryColumns>"; int count = 0; while (true) { count++; XmlNode results = null; try { results = listService.GetListItems(listName, null, query, viewFields, rowLimit, queryOptions, webID); } catch (Exception ex) { } try { foreach (System.Xml.XmlNode listItem in results) { XmlNodeReader objReader = new System.Xml.XmlNodeReader(listItem); while (objReader.Read()) { if (objReader["ows_EncodedAbsUrl"] != null) { SiteUrlList.Add(objReader["ows_EncodedAbsUrl"].ToString()); } } } } catch (Exception ex) { } positionNext = results.SelectSingleNode("//@ListItemCollectionPositionNext"); if (positionNext == null) break; else queryOptions.InnerXml = "<Paging ListItemCollectionPositionNext='" + positionNext.InnerXml + "' /><IncludeMandatoryColumns>False</IncludeMandatoryColumns>"; } return SiteUrlList; }
To Copy the documents from MOSS 2007 document library to SharePoint 2010 document library.
public void UploadDoc(string SourceUrl, string DestUrl, string DestFolderName, string DestFileName) { NetworkCredential custCred2007 = new NetworkCredential(ConfigurationManager.AppSettings["SP2007user"], ConfigurationManager.AppSettings["SP2007pwd"]); NetworkCredential custCred2010 = new NetworkCredential(ConfigurationManager.AppSettings["SP2010user"], ConfigurationManager.AppSettings["SP2010pwd"],ConfigurationManager.AppSettings["SP2010domain"] ); try { SPcopyservices2007.Copy WebSvc2007 = new SPcopyservices2007.Copy(); SPcopyservices2010.Copy WebSvc2010 = new SPcopyservices2010.Copy(); WebSvc2007.Credentials =custCred2007; WebSvc2010.Credentials = System.Net.CredentialCache.DefaultCredentials; string copySource =HttpUtility.UrlDecode( SourceUrl); string[] copyDest = {HttpUtility.UrlDecode(string.Format("{0}/{1}/{2}", DestUrl,DestFolderName, DestFileName))}; SPcopyservices2010.FieldInformation myfldinfo2010 = new SPcopyservices2010.FieldInformation(); SPcopyservices2010.FieldInformation[] myFieldInfoArray2010 = { myfldinfo2010 }; byte[] myByteArray; WebSvc2010.Url = ConfigurationManager.AppSettings["SrcWebservcUrl"].ToString() + "_vti_bin/Copy.asmx"; WebSvc2010.Credentials = custCred2007; uint myGetUint = WebSvc2010.GetItem(copySource, out myFieldInfoArray2010, out myByteArray); WebSvc2007.Dispose(); WebSvc2010.Dispose(); SPcopyservices2010.CopyResult myCopyResult1 = new SPcopyservices2010.CopyResult(); SPcopyservices2010.CopyResult myCopyResult2 = new SPcopyservices2010.CopyResult(); SPcopyservices2010.CopyResult[] myCopyResultArray = { myCopyResult1, myCopyResult2 }; try { WebSvc2010 = new SPcopyservices2010.Copy(); WebSvc2010.Url = ConfigurationManager.AppSettings["DestWebservcUrl"].ToString() + "_vti_bin/Copy.asmx"; WebSvc2010.Credentials = custCred2010; uint myCopyUint = WebSvc2010.CopyIntoItems(copySource, copyDest, myFieldInfoArray2010, myByteArray, out myCopyResultArray); if (myCopyUint == 0) { int idx = 0; foreach (SPcopyservices2010.CopyResult myCopyResult in myCopyResultArray) { string opString = (idx + 1).ToString(); if (myCopyResultArray[idx].ErrorMessage == null) { //Successfully moved } else { //Error occured } idx++; } } } catch (Exception exc) { int idx = 0; foreach (SPcopyservices2010.CopyResult myCopyResult in myCopyResultArray) { idx++; if (myCopyResult.DestinationUrl == null) { } } } finally { if (WebSvc2010 != null) WebSvc2010.Dispose(); } } catch (Exception ex) { } }
Conclusion:
We can use the above steps, configurations and codes to copy the document to a different server (or from a different server) with the document metadata information. During Migration of documents from an old SharePoint environment to a new SharePoint environment this technique is very helpful. We can also recursively get all the documents from all folders and subfolders of source environment using the appropriate CAML query.
Thank you for your work!
I have only one week for moving files from 2007 to 2013.