Deep Dive into the SharePoint Content Deployment and Migration API – Part 4


[Part 1Part 2Part 3Part 4Part 5 – Part 6 – Part 7]

Advanced content deployment scenarios

Till now we have covered export and import of

  • single list items or documents
  • containers like folders, lists or webs
  • complete site collection

What we haven’t covered is how to use this method to move items. Or how to control the which items from the export package need to get imported into the database.

Let’s look on each of these topics separately.


1) Moving content using Content Deployment and Migration API

Export and import allows us to create a copy of items or containers but it does not automatically allow us to move content. But copying the content and then deleting the original content is very similar to a real move operation. the only problem here is that links pointing to the moved content will still point to the original content. So these would have to be adjusted.

And this is indeed what the Move operation in Site Manager does! It copies the content using the Content Deployment and Migration API, adjusts all links to point to the new content and then delete the original content.

Let’s now look on a sample how this can be achieved by looking at a sample code for the move of a single image from an image library.

First step is to export the ListItem using the Content Deployment and Migration API as demonstrated in part 2:

// export an image from the Images Library

SPSite site = new SPSite("http://localhost:2000");
SPWeb web = site.OpenWeb("/SourceSubWeb");
SPList list = web.Lists["Images"];
SPListItem listItem = list.Items[0];

SPExportObject exportObject = new SPExportObject();
exportObject.Id = listItem.UniqueId;
exportObject.Type = SPDeploymentObjectType.ListItem;

SPExportSettings exportSettings = new SPExportSettings();
exportSettings.ExportObjects.Add(exportObject);
exportSettings.FileLocation = @"c:\export";
exportSettings.FileCompression = false;
exportSettings.SiteUrl = "http://localhost:2000";

SPExport export = new SPExport(exportSettings);
export.Run();

// cleanup
web.Dispose();
site.Dispose();

The next step is to import the image from the export into a the desired new location similar to the steps described in part 3:

// import the image into the desired destination library

SPImportSettings importSettings = new SPImportSettings();
importSettings.SiteUrl = “http://localhost:2000”;
importSettings.FileLocation = @”c:\export”;
importSettings.FileCompression = false;
importSettings.RetainObjectIdentity = false;

SPImport import = new SPImport(importSettings);

EventHandler<SPDeploymentEventArgs> startedEventHandler = new EventHandler<SPDeploymentEventArgs>(OnStarted);
import.Started += startedEventHandler;

EventHandler<SPObjectImportedEventArgs> importedEventHandler = new EventHandler<SPObjectImportedEventArgs>(OnImported);
import.ObjectImported += importedEventHandler;

import.Run();

// event handler to assign a new parent to the orphaned image in the package

static void OnStarted(object sender, SPDeploymentEventArgs args)
{
   SPSite site = new SPSite("http://localhost:2000");
   SPWeb web = site.OpenWeb("/MyWeb");
   SPList list = web.Lists["Images"];

   SPImportObjectCollection rootObjects = args.RootObjects;
   foreach (SPImportObject io in rootObjects)
   {
      io.TargetParentUrl = list.RootFolder.ServerRelativeUrl;
   }

   web.Dispose();
   site.Dispose(); 
}

If you look at the code above you will see that there is one additional event handler registered with the import object. This event handler will fire every time a new object has finished importing. We will now use this event handler to finish the move operation by changing all links pointing to the original image to the new image and afterwards deleting the original image.

Lets look into the details.

The event handler gets the Url of the exported object and the Url of the imported object in the SPObjectImportedEventArgs:

  • SourceUrl
  • TargetUrl

Based on this information the following code will now give us the SPListItem object of the original image from the SourceUrl property.

string url = eventArgs.SourceUrl;
SPSite site = new SPSite(import.Settings.SiteUrl);
SPWeb web = site.OpenWeb(url, false);
SPListItem li = web.GetListItem(url); 

As next step we retrieve the number of backward links pointing to the original image. A backward link means that another object points to this object. A forward link on the other hand would point from the current object to a different object. Using the BackwardLinks collection we are able to identify all objects that a point to the exported object.

To adjust all links we need to follow all backward links pointing to the original object to adjust the links to point to the new object we get the links using the following code:

int count = li.BackwardLinks.Count; 
for (int i = count - 1; i >= 0; i--) 

   SPLink link = li.BackwardLinks[i]; 
   ...

Now we need to get the objects that are pointing to our source item by following the ServerRelativeUrl in each backward link:

SPLink link = li.BackwardLinks[i];
 
using (SPWeb rweb = linkSite.OpenWeb(link.ServerRelativeUrl, false)) 

   object o = rweb.GetObject(link.ServerRelativeUrl);
   …
}

Now we known the object. The next step is to adjust the forward link. But to adjust the link we first have to cast the retrieved object to it’s actually SharePoint type.

There are exactly two different object types that can create a link to our image: SPListItem and SPFile as these are the only object types that implement the ForwardLink property. And these objects also implement a method to adjust the forward link by replacing the link to the exported object with the link of the imported object:

object o = rweb.GetObject(link.ServerRelativeUrl);
if (o is SPFile)
{
   SPFile f = o as SPFile;
   f.ReplaceLink(eventArgs.SourceUrl, eventArgs.TargetUrl);
}
if (o is SPListItem)
{
   SPListItem l = o as SPListItem;
   l.ReplaceLink(eventArgs.SourceUrl, eventArgs.TargetUrl);
}

After we have successfully adjusted all links we can then savely delete the source image.

Here is the complete code for our event handler:

static void OnImported(object sender, SPObjectImportedEventArgs eventArgs)
{
   SPImport import = sender as SPImport;

   string url = eventArgs.SourceUrl;
   SPSite site = new SPSite(import.Settings.SiteUrl);
   SPWeb web = site.OpenWeb(url, false);
   SPListItem li = web.GetListItem(url);

   int count = li.BackwardLinks.Count;
   for (int i = count - 1; i >= 0; i--)
   {
      SPLink link = li.BackwardLinks[i]; 
      using (SPWeb rweb = site.OpenWeb(link.ServerRelativeUrl, false)) 
      { 
         object o = rweb.GetObject(link.ServerRelativeUrl); 
         if (o is SPFile) 
         { 
            SPFile f = o as SPFile; 
            f.ReplaceLink(eventArgs.SourceUrl, eventArgs.TargetUrl); 
         } 
         if (o is SPListItem) 
         { 
            SPListItem l = o as SPListItem; 
            l.ReplaceLink(eventArgs.SourceUrl, eventArgs.TargetUrl); 
         }
      }
   }
   li.Delete();

   web.dispose();
   site.dispose();
}

 

You can try this sample by creating a publishing site, create a sub web and upload an image to the “Images” library. Then create a page based on a page layout that has a Image Field and reference the uploaded image in this field. Now use the code shown above to move the image to the “Images” library in a different web.


2) How to control which of the objects in the export package need to be imported

The Content Deployment and Migration API itself does not provide a possibility to select specific objects for import. It will always import all objects included in the export package. In order to control which objects to import we again need to intercept the import using the “Started” event handler and remove all objects from the package that should not be imported.

This can be done using code similar to the following:

static void OnStarted(object sender, SPDeploymentEventArgs args) 

   
// assign new parents to the root objects if required.
   ...
   
// get the information about the location of the manifest file after decompression (if required)

   string tempFileLocation = args.TempDirectoryPath;
   
   // now we need get all manifest files from the SystemData.xml file in the tempdirectory path
   StringCollection manifestFilenames = GetManifestFilenamesFromSystemDataXmlFile(args.TempDirectoryPath + @"\SystemData.xml"); 

   // now we can manipulate the content of each of the manifest files and (e.g.) remove objects from the manifest.
   foreach (string manifestFilename in manifestFilenames)
   {
       DoTheRequiredManipulationsToTheManifestFiles(manifestFilename);
   }

The SystemData.xml file and the Manifest.xml files can be manipulated using normal Xml operations available in .Net framework.

Important to know when planning to manipulate the Manifest.xml files that each individual exported objects is reflected as a SPObject node. The SPObject nodes are sequentially serialized inside the manifest file. That means that subwebs are listed behind their parent webs but not as child xml nodes.

Now I see the following question coming up: Is it allowed to manipulate the Manifest.xml files?

The answer is yes! The xml schema of all the xml files in a content migration pack is officially documented and can (e.g.) be used by 3rd party companies to migrate content to WSS or MOSS:
http://msdn2.microsoft.com/en-us/library/bb249989.aspx

Comments (73)

  1. Anonymous says:

    Stefan is back! J Stefan is in Redmond this week, and we had a chance to catch up! In fact, I had dinner

  2. Anonymous says:

    Stefan Goßner taucht in einer vierteiligen Serie in die Tiefen der SharePoint Deployment und Migration

  3. Anonymous says:

    Fantastic, incredibly detailed, content on content deployment by Stefan

  4. Anonymous says:

    [via Stefan Gossner ] This past week I was in Redmond teaching my WCM401 development class in an open

  5. Anonymous says:

    Body: Great series of posts by Stefan on how to use the Content Migration API. Very timely for me as

  6. Anonymous says:

    今天凌晨加班的时候偶然翻到 Stefan Gossner 的这几篇文章,强烈推荐给大家: Deep Dive into the SharePoint Content Deployment and Migration

  7. yair says:

    Grate post, thanks.

    But, what if my manifast.xml files weighs over 200 MB?

  8. Stefan Goßner says:

    Hi Yair,

    it shouldn’t matter. But if you are concerned about this use the FileMaxSize export property.

    This also controls the size of the generated manifest.

    So you will end up with multiple manifest files then.

    Cheers,

    Stefan

  9. Luis Sousa says:

    Hi,

    Your post was the best on content deployment with MOSS that I found on the internet. Better that MSDN documentation. 🙂

    I wonder if you don’t want to extend this article, with a part 5, where you can explain which of these features are available and work in websites with variations.

    Congratulations!

  10. Anonymous says:

    Great set of articles by Stefan Goßner : Deep Dive Into the SharePoint Content Deployment…

  11. Anonymous says:

    MOSS / SharePoint Content Deployment

  12. Hi, Stefan!

    Can you explain why I receive some error messages on trying to migrate content between two MOSS machines. First machine was installed on english SKU, with 3 variations: english, serbian-latin and serbian-cyrillic. On that installation I installed language pack for serbian-latin when it became available. Second machine (destination) is empty moss with english sku and serbian language pack.

    Here are error details:

    Could not find language Serbian (Latin, Serbia). at Microsoft.SharePoint.Deployment.ImportRequirementsManager.VerifyInstalledLanguage(String id, String name) at Microsoft.SharePoint.Deployment.ImportRequirementsManager.VerifyLanguage(SPRequirementObject reqObj) at Microsoft.SharePoint.Deployment.ImportRequirementsManager.Validate(SPRequirementObject reqObj) at Microsoft.SharePoint.Deployment.ImportRequirementsManager.DeserializeAndValidate() at Microsoft.SharePoint.Deployment.SPImport.VerifyRequirements() at Microsoft.SharePoint.Deployment.SPImport.Run()

    Thanks!

    Dragan

  13. Stefan Goßner says:

    Hi Dragan,

    you need to install the same language pack on both machines.

    Cheers,

    Stefan

  14. Nita Arvind says:

    Hi Stefan,

    Me team is in a fix. We have some documents in a folder structure in a Content Management Application called Plumtree. Some of these Word documents have hyperlinks to eachother.

    The requirement is for us to move these files and the folder structure as it is to a document library in sharepoint- this we are able to accomplish.

    The next phase of the requirement was to update the hyperlinks in the documents with the new sharepoint URL. We are able to accomplish this in most cases using the SPfile.ReplaceLink function. But there are instances where this fails.

    Eg: OLD URL: http://www.google.com?id=123

    NEW URL: http://www.yahoo.com

    It does nothing.

    Is there something we might be doing wrong.

    It works fine in cases where :

    OLD URL: http://www.google.com/games.html

    NEW URL: http://www.yahoo.com

  15. Stefan Goßner says:

    Hi Nita,

    please open a support case for this.

    This needs to be analyzed in more details.

    Cheers,

    Stefan

  16. Anonymous says:

    useful links for sharepoint 2007 customization

  17. AllTec says:

    Hi

    I want to migrate my content(documents in folder structure) from plumtree to MOSS 2007. How I should go ahead with this migration?

    Thanks

    AllTec

  18. Stefan Goßner says:

    Hi AllTec,

    you would need to create a Content Deployment and Migration Package from the Plumtree content.

    So you would need to write or purchase a tool that reads the content from Plumtree and creates the package. Then import the package into SharePoint.

    The schema the package content has to follow is defined here:

    http://msdn2.microsoft.com/en-us/library/bb249989.aspx

    Cheers,

    Stefan

  19. paul says:

    Hi stefan,

    I like to know where the settings(e.g. authentification) for the target Sharepoint will be handled, if the target system is in a differnet domain than the source. I can´t see anything around the SPImport class that could help.

    best regards

    Paul

  20. Stefan Goßner says:

    Hi Paul,

    there seems to be a misunderstanding.

    SPImport can only be used against the local machine – not remotely.

    Cheers,

    Stefan

  21. Anonymous says:

    Stefan Goßner posted a great series of posts about the Content Migration API (formerly known as PRIME

  22. ML49448 says:

    Is this an approach that could be used to export a particular content type and import it into a totally new content type?

    Is there an event that could override which site column/field control the content is imported into?  Or will you end up importing the content – and then changing the content types?

  23. Stefan Goßner says:

    Hi Michael,

    you would need to modify the export package to achieve this before importing.

    Cheers,

    Stefan

  24. Anonymous says:

    [ Part 1 – Part 2 – Part 3 – Part 4 – Part 5 – Part 6 ] Requirements for a successful content deployment

  25. Roopa says:

    Hey,

    I am trying to export and import a list which is having folders and sub folders within.Can you please tell me how to import items to the respective subfolders. presently, all the items are moving to the root folder.

  26. Stefan Goßner says:

    Hallo Roopa,

    this is discussed in section "2) Change the Parent of the imported objects during Import" of part 3.

    Cheers,

    Stefan

  27. roopa says:

    Hey Stefan,

    I have been trying to import a list.Export is goin on proper but, while import the following error is logged in :

    ————————————————

    [10/21/2008 1:42:54 PM]: Start Time: 10/21/2008 1:42:54 PM.

    [10/21/2008 1:42:54 PM]: Progress: Initializing Import.

    [10/21/2008 1:42:54 PM]: Progress: Starting content import.

    [10/21/2008 1:42:54 PM]: Progress: De-Serializing Objects to Database.

    [10/21/2008 1:42:54 PM]: Progress: Importing Folder /abc/xyz/Lists/list for calenders/Item.

    [10/21/2008 1:42:55 PM]: Progress: Importing ListItem /abc/xyz/Lists/list for calenders?id=6.

    [10/21/2008 1:42:55 PM]: Error: Invalid file name

    The file name you specified could not be used.  It may be the name of an existing file or directory, or you may not have permission to access the file.

      at Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish)

      at Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, Boolean bPreserveItemVersion, Boolean bNoVersion, Boolean bMigration, Boolean bPublish, Boolean bCheckOut, Boolean bCheckin, Guid newGuidOnAdd, Int32& ulID, Object& objAttachmentNames, Object& objAttachmentContents, Boolean suppressAfterEvents)

      at Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, Boolean bPreserveItemVersion, Guid newGuidOnAdd, Boolean bMigration, Boolean bPublish, Boolean bNoVersion, Boolean bCheckOut, Boolean bCheckin, Boolean suppressAfterEvents)

      at Microsoft.SharePoint.SPListItem.MigrationAddOrUpdate(Boolean bAddNew, Boolean bIsPublish, Guid newGuidOnAdd, Boolean bNoVersion, Boolean suppressAfterEvents)

      at Microsoft.SharePoint.Deployment.ListItemSerializer.SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)

    [10/21/2008 1:42:55 PM]: Progress: Import Completed.

    ————————————————–

    I have no clue why is this happening.Please do suggest what might be the reason.

    Thanks in advance,

    Roopa.

  28. Stefan Goßner says:

    Hi Roopa,

    the problem code be the last item listed in the log and with the same possibility the next item that would be imported.

    To analyze this further it would be required to analyze a memory dump for this exception.

    Please open a support case for this to get this analyzed in more detail.

    Cheers,

    Stefan

  29. rajee says:

    hi stefan,

           I have two custom menus which will be given to the user.When two users try to run at same time it is executing only one job at a time.so how to handle this issue so that all the users are able to acess these custom menus for the deployments.Is there any way to create a job programtically.

    Regards,

    Rajee

  30. Stefan Goßner says:

    Hi Rajee,

    you need to ensure that the jobs are not running in parallel as the content deployment and migration API is not designed to run more than one job at a time.

    Also: did you already check out the quick deploy function? Because what you are talking about sounds like the functionality provided by this function.

    Cheers,

    Stefan

  31. rajee says:

    hi stefan,

       I tried searching for this quick deploy function but dint get any proper information on this.How to create a Quick deployment job and run that job programtically.

    Cheers,

    Rajee

  32. Stefan Goßner says:

    Hi Rajee,

    the quick deploy job gets automatically created when you create a content deployment path between two site collections where the source site collection has the publishing feature enabled.

    A publishing site collection is required for this feature. You cannot use it with team sites (e.g.)

    Cheers,

    Stefan

  33. rajee says:

    hi stefan,

      In our case we have some hundereds of sites which will have pages library.on those libraries we activated the custom menus.In our case we have internet users where they can move the pages to the Archival Site. I tried creating the Content Deployment path by using Central administrator.Mapping is very problematic as there are so many sites.

    So is there any way to create content deployment path programtically so that we can create the path and update those details.Once deployment is done so that we can delete that path.If parallel jobs are there we will create two paths and run the job at different times.

    Cheers,

    Rajee

  34. Stefan Goßner says:

    Hi Rajee,

    it would be required to create a path that copies content into a different location of the current site.

    That is not possible. Neither programmatic nor manual.

    You need to do this manually using the content deployment and migration API.

    I would suggest to implement the console action as an action that writes the information what to copy in a list and implement the real copy operation as custom SharePoint timer job and execute it in OWSTIMER as it is done with the other content deployment jobs. This job then has to read the list to get the info what to deploy.

    Then you don’t have to bother about synchronization problems between actions.

    Cheers,

    Stefan

  35. rajee says:

    Hi stefan,

        Thank you so much.What ever content you have provided in this bolg is fantastic.Really very useful for the content migration.

    Cheers,

    Rajee

  36. Rajee says:

    hi stefan,

       I am trying to import the Custom List Items i am getting error "Invalid Filename you specified couldn’t be used.It may be the name of the exsistingfile or directory,or you may not have permission to access the file."

    what could be the reason for this.

    Cheers,

    Rajee

  37. Stefan Goßner says:

    Hi Rajee,

    I haven’t seen this issue.

    I would suggest to open a support case to get this analyzed in more detail.

    Cheers,

    Stefan

  38. Rajee says:

    hey stefan,

         We tried importing a page from One site collection to another site collection on different port.Import is sucessful but when we tried opening the page every time i am getting the "File Not found" error.

    when we check the ULS Logs we are getting the error as "Medium   Unknown SPRequest error occurred. More information: 0x80070002

    "01/14/2009 07:27:45.00  w3wp.exe (0x0368)                        0x1048 Windows SharePoint Services    General                        8nca Verbose  Application error when access /site1/site2/site3/site4/Pages/samplepage.aspx, Error=The file /site1/_catalogs/masterpage/samplelayout.aspx does not exist.

    we can see the imported page in the Pages library.

    I have no clue why is this happening..Please suggest the what could be the reason for this.

    Cheers,

    Rajee    

  39. Stefan Goßner says:

    Hi Rajee,

    does the page layout exist as well?

    The error message indicates that the page layout is missing – not the page itself.

    Cheers,

    Stefan

  40. Rajee says:

    hi Stefan,

          Page layout is there in the destination site.But when we tried opening the page we are getting this kind of Trace logs.why this page layout is not getting attached to the page which is imported in to the pages library.

    Cheers,

    Rajee

  41. Stefan Goßner says:

    Hi Rajee,

    it seems it is attached – otherwise it would not try to load it from this location. But it seems the file cannot be opened for some reason.

    Please open a support case with Microsoft to analyze what is causing the issue on your site.

    Cheers,

    Stefan

  42. STA says:

    Hi Stefan,

    Your post is very useful for me. I’m trying to export/import SPList from site to site. And I found that SPExportMethodType.ExportChanges cannot be used for SPList level. I think other way around is exporting site or web level with SPExportMethodType.ExportChanges. And then remove unnecessary things from manifest.xml file with eventhandler. Is it possible to do so? And I found Manifest.xml file has a lot of ObjectTypes, can I remove only ObjectType="SPList"?  Please give me idea.

    Thanks,

    STA

  43. Stefan Goßner says:

    Hi STA,

    you can modify the manifest.xml file to get what you are looking for.

    For details about what has to exist in the manifest file (which will allow you to decide what can be removed) can be found here:

    http://msdn2.microsoft.com/en-us/library/bb249989.aspx

    Cheers,

    Stefan

  44. STA says:

    Hi Stefan,

    Thanks for your advice, I have another question. I need to synchronize two lists from different sites. I wonder Content Migration API can handle deleted items or not. After I run SPImport, all the items I deleted in source site are still remaining in destination site. with SPExportMethodType.ExportChanges.

    Thanks,

    STA

  45. Stefan Goßner says:

    Hi STA,

    export changes works on SPWeb level. Then it will only export changed list items.

    Cheers,

    Stefan

  46. Lawrence says:

    Is there a way to migrate a single list item so that it updates the corresponding item in the target list rather than adding a new item to the list?

    we have a customer who has their own copy of a SP site we created, and we would like to migrate any changes we make in ours to theirs. We have done some trial migrations but discovered that any updated items in our list always results in a new item in their list.

    Our main issue is maintaing the list item ID.  If we update item ID=12 for example in our list, we want the migration to replace ID=12 in their list, whereas at the moment it is creating ID=99 (say) and still retaining ID=12.

    The reason for this is because of lookups on that list. If another list points to ID=12 then we don’t want to retarget that so it points to ID=99 (unless we have to = and if so, how could we do that in bulk….?)

    thanks for any guidance you can give.

  47. Stefan Goßner says:

    Hi Lawrence,

    updates to items are only supported with RetainObjectIdentity.

    That means that the GUID and URL need to be the same on the target.

    So you cannot do this together with reparenting.

    Cheers,

    Stefan

  48. Lawrence says:

    Thanks Stefan.

    So as I understand it, if we used RetainObjectIdentity that would work internally where we want to migrate content between

    mydomain/siteA to mydomain/siteB

    but not externally for

    mydomain/siteA to theirdomain/siteA

  49. Stefan Goßner says:

    Hi Lawrence,

    that is not correct. It will work for different domains as well.

    Cheers,

    Stefan

  50. SHarepoInT says:

    can you please give a continuos, complete, and tested code example for exporting a list item and then importing it into a different list from start to finish? i have tried desperately to piece this code together but no matter what i do i get errors. when i click ‘debug’ my computer bursts into flames. plz help

  51. Stefan Goßner says:

    Hi SHarepoInT,

    working code is below.

    Cheers,
    Stefan

     

    using System;

    using System.Collections.Generic;

    using System.Text;

    using Microsoft.SharePoint;

    using Microsoft.SharePoint.Deployment;

    namespace WssOMtest

    {

       class Program

       {

           static void Main(string[] args)

           {

               // export

               SPSite site = new SPSite("http://localhost:4000&quot;);

               SPWeb web = site.OpenWeb("/");

               SPList list = web.Lists["MyList"];

               SPListItem listItem = list.Items[0];

               SPExportObject exportObject = new SPExportObject();

               exportObject.Id = listItem.UniqueId;

               exportObject.Type = SPDeploymentObjectType.ListItem;

               SPExportSettings exportSettings = new SPExportSettings();

               exportSettings.ExportObjects.Add(exportObject);

               exportSettings.FileLocation = @"c:exportCopyListItem";

               exportSettings.FileCompression = false;

               exportSettings.SiteUrl = "http://localhost:4000&quot;;

               SPExport export = new SPExport(exportSettings);

               export.Run();

               web.Dispose();

               // import

               SPImportSettings importSettings = new SPImportSettings();

               importSettings.SiteUrl = "http://localhost:4000&quot;;

               importSettings.FileLocation = @"c:exportCopyListItem";

               importSettings.FileCompression = false;

               importSettings.RetainObjectIdentity = false;

               SPImport import = new SPImport(importSettings);

               EventHandler<SPDeploymentEventArgs> startedEventHandler = new EventHandler<SPDeploymentEventArgs>(OnStarted);

               import.Started += startedEventHandler;

               import.Run();

               // cleanup

               site.Dispose();

           }

           // event handler to assign a new parent to the orphaned image in the package

           static void OnStarted(object sender, SPDeploymentEventArgs args)

           {

               SPSite site = new SPSite("http://localhost:4000&quot;);

               SPWeb web = site.OpenWeb("/PressReleases");

               SPList list = web.Lists["TargetList"];

               SPImportObjectCollection rootObjects = args.RootObjects;

               foreach (SPImportObject io in rootObjects)

               {

                   io.TargetParentUrl = list.RootFolder.ServerRelativeUrl;

               }

               web.Dispose();

               site.Dispose();

           }

       }

    }

  52. Rajee says:

    hi stefan,

     We are facing one critical problem while importing the page into another Webapplication

    Below is the Error Log for that

    The Web application at
    http://son15873:22232/dealer/uskw/en/parts/supplierdocumentation/srdview1 could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping
    to the intended application.

    Please suggest what might be reason for this?

  53. Stefan Goßner says:

    Hi Rajee,

    I assume you already verified that the URL is valid, right? I haven’t seen this error in such a situation. Please open a support case with Microsoft. to get this analyzed.

    Cheers,

    Stefan

  54. SHarepoInT says:

    Hey Stefan,

    Do you know if there’s a way to retain permissions on a list item through this process? I’ve tried using IncludeSecurity = SPIncludeSecurity.All on export and import but it doesnt look like that has anything to do with permissions. Is there another setting or combination of settings that does this?

    Thanks

  55. SHarepoInT says:

    To update my last post, It turns out that IncludeSecurity = SPIncludeSecurity.All IS the way to retain permssions. The problem I’m having is that it doesnt work if the source and target are in different application pools. Neither does copying role assignments one by one, or pretty much anything else item, list, web, site, or sharepoint related. So, if you happen to know a way to get permissions across application pools that would be great but this probably isnt import/export related anymore so I’ll understand if it doesnt get much attention

  56. Stefan Goßner says:

    Hi SHarepoInT,

    this should work if you set SPImportUserInfoDateTime to ImportAll.

    Cheers,

    Stefan

  57. SharePoint List Migration says:

    Stefan,

    I want to start off by thanking you for all the time and effort spent sharing your expertise with the SharePoint community.

    The Problem: Migrating ListItems between two sites (A -> B) while preserving ID and author/editor info.  The content type of List B is different from List A (B has additional columns defined).  

    From your posts my understanding is that: 1) ListItem ID can be preserved setting RetainObjectIdentity = true (does this only preserve List GUID or also ListItem IDs?)

    2) Author/editor info can be preserved using the UserInfoDateTime setting.

    Is it possible to leverage the migration api if there are differences between original and destination list content types?  Are there alternatives?

    Any insight would be greatly appreciated.

  58. Stefan Goßner says:

    Hi,

    1) it will preserve the GUID of list and item. I don’t think it will preserve the integer ID of the item. That can change when being imported on the target

    2) no that is not possible.

    Cheers,

    Stefan

  59. SharePoint List Migration says:

    Thanks for the prompt reply.  

    To clarify point 2)

    You are saying that there is no way to use the migration api if:

    Source List (field A, field B) and

    Destination List (field A, field B, field C)

    I cannot import only field A and field B data to the destination list?

  60. Stefan Goßner says:

    In case that the target list has the same columns plus some additional it will work. Means the additional columns are empty.

    But you cannot remap the columns from one column to another one.

  61. narendra says:

    Stefan,

    I have a MOSS installation for intranet and we are planning to use WSS for internet web facing site. The WSS is sitting at some hosting provider. Could I be able to export my MOSS content to the external facing WSS site using the technics that you are showing here.

    Thanking you

    Narendra

  62. Stefan Goßner says:

    Hi Narendra,

    only if the site does not use any MOSS specific features.

    Cheers,

    Stefan

  63. narendra says:

    Hi Stefan,

    Some where you said,

    SPImport can only be used against the local machine – not remotely.

    I thought content won’t be copying accross domains!

    Thanks for this.

    Second question,

    How can I do this 🙂 Little bit of insights please.

    Thanking you very much.

  64. Stefan Goßner says:

    Hi Narendra,

    the info is correct. SPImport can only be used against the local farm. But you can copy on one farm, transfer the package to the target farm and then run SPImport there.

    Cheers,

    Stefan

  65. s says:

    Hi Stefan,

    Do you have any idea how to get backward links from other SPWebApplications? The BackwardLinks collection doesnt include them.

    I’m thinking about trying to use a search but I thought I’d ask in case you know an easier way.

  66. Stefan Goßner says:

    Hi,

    SharePoint manages links only within the same site collection. Links to other site collections are treated as external links. You will not find them in the BackwardLinks collection.

    For such links you would need to implement your own link management.

    Cheers,

    Stefan

  67. Frankie says:

    Dear Stefan,

     How are you doing? I have a question need you to clarify as below:

     As you mentioned "Content deployment will always import all objects included in the export package." If there is a page edited by user and is still waiting for approval, it will also be exported when the deployment job run, is it right? If the answer is yes, then when it be imported on produciton server, the page will show error and could not be opened coz it’s not a publish page. How we could handle this? Should we using the "Started" event handler and remove all objects from the package that should not be imported.

    Please give advise. Many thanks!

    Frankie

  68. Stefan Goßner says:

    Hi Frankie,

    it will be as on the source site. If the page is not approved the latest approved version will show up for users with only read permission.

    Cheers,

    Stefan

  69. Shiv says:

    Hi Stefan,

    I am working on a requirement which will take a back of a site and then restore that later, if needed.

    Since it’s a site not site collection so i thought of using the SPExport/SPimport APIs.

    It’s backing me up and then later restoring all the files and folders but not any of the users of the source site. I am using "IncludeSecurity = SPIncludeSecurity.All" and "UpdateVersions = SPUpdateVersions.Append" for both SPExport and SPImport.

    How can i take a backup of all the users of a site?

    Does SPExport/SPImport migrate users also?

    I appreciate your comments in this regards.

    Thanks,

    Shiv

  70. Stefan Goßner says:

    Hi Shiv,

    SPExport/SPImport is not a replacement for backup/restore.

    The API is intended to export content and associated security information. But you cannot (e.g.) export only all the users.

    If content is exported then you can decide whether security information for the exported items should be included in the package or not.

    If SPIncludeSecurity.All is chosen then all users related to the exported content will be exported as well.

    Cheers,

    Stefan

  71. Sameer says:

    Stefen,

    I wish to migrate all the available sites/sub sites from SharePoint 2003 to MOSS 2007.

    Will this SPExport/SPImport work in this scenario as well?

    Appreciate your help in this regard.

    Regards

    Sameer

  72. Stefan Goßner says:

    Hi Sameer,

    no this cannot be done because there is no SPExport in SPS 2003.

    Cheers,

    Stefan

  73. MMRahman says:

    Hi Stefan,

    Great Post.   I am getting  “Cannot complete this action. Please try again.”  error on import. I am exporting and importing folder (with sub folders and documents  in it )  from Document Library  from a custom web part.  

    Do you have  any idea what is the meaning of the following error and how to get rid of this?  

    Thank you in advance for your valuable time and effort.

    -MMRAhman

    Error:   “Cannot complete this action. Please try again.”

    stackTrace :

    [8/1/2010 10:54:24 PM]: Progress: Starting content import.

    [8/1/2010 10:54:24 PM]: Progress: De-Serializing Objects to Database.

    [8/1/2010 10:54:24 PM]: Progress: Importing Folder /sites/projects/mmr/Documents/Forms/Document.

    [8/1/2010 10:54:24 PM]: Progress: Importing Folder /sites/projects/mmr/Documents/Forms/Folder.

    [8/1/2010 10:54:24 PM]: FatalError: Cannot complete this action.

    Please try again.

      at Microsoft.SharePoint.Library.SPRequest.UpdateField(String bstrUrl, String bstrListName, String bstrXML)

      at Microsoft.SharePoint.SPField.set_SchemaXml(String value)

      at Microsoft.SharePoint.Deployment.ContentTypeSerializer.UpdateContentTypeFields(SPContentType sourceContentType, SPContentType targetContentType, String contentTypeXml, ImportObjectManager importObjectManager)

      at Microsoft.SharePoint.Deployment.ContentTypeSerializer.UpdateContentType(SPContentType sourceContentType, SPContentType targetContentType, String contentTypeXml, ImportObjectManager importObjectManager)

      at Microsoft.SharePoint.Deployment.ContentTypeSerializer.ProcessContentType(SPContentType sourceContentType, String contentTypeXml, ImportObjectManager importObjectManager, Boolean IsParentSystemObject)

      at Microsoft.SharePoint.Deployment.ContentTypeSerializer.SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)

      at Microsoft.SharePoint.Deployment.XmlFormatter.ParseObject(Type objectType, Boolean isChildObject)

      at Microsoft.SharePoint.Deployment.XmlFormatter.DeserializeObject(Type objectType, Boolean isChildObject, DeploymentObject envelope)

      at Microsoft.SharePoint.Deployment.XmlFormatter.Deserialize(Stream serializationStream)

      at Microsoft.SharePoint.Deployment.ObjectSerializer.Deserialize(Stream serializationStream)

      at Microsoft.SharePoint.Deployment.ImportObjectManager.ProcessObject(XmlReader xmlReader)

      at Microsoft.SharePoint.Deployment.SPImport.DeserializeObjects()

      at Microsoft.SharePoint.Deployment.SPImport.Run()

    [8/1/2010 10:54:24 PM]: Progress: Import Completed.

    [8/1/2010 10:54:24 PM]: Finish Time: 8/1/2010 10:54:24 PM.

    [8/1/2010 10:54:24 PM]: Completed with 0 warnings.

    [8/1/2010 10:54:24 PM]: Completed with 1 errors.