Mark Jones' Blog

All posts

Content Migration using SAF

-

SAF contains 6 ready-to-use Actions that allow the Exporting and Importing of :

- List Items

- Lists

- Webs

The 3 pairs of Actions that allow you to do this, are namely :

- ExportListItem & ImportListItem

- ExportList & ImportList

- ExportWeb & ImportWeb

The actions are listed as pairs, for convenience, although there is nothing that mandates that they have to be run one after the other. In fact, you can export a List and import it into a completely different Farm months later if you so wish. In addition to this, although each pairing exports and imports different types of content, they all follow the same process, which is  :

1. Export to a Content Migration Package (CMP) according to settings specificied in the “Export” Action.

2. Import from a CMP file according to settings specificed in the “Import” Action.

In principal that’s it! If you download the source code from here : http://SAF.Codeplex.com, you will find some useful examples at the locations listed below :

  1. {YourDrive}\src\CollaborisSaf.SampleFeatures\12\TEMPLATE\FEATURES\WSS.ContentMigration.CopyListItem
  2. {YourDrive}\src\CollaborisSaf.SampleFeatures\12\TEMPLATE\FEATURES\WSS.ContentMigration.CopyList
  3. {YourDrive}\src\CollaborisSaf.SampleFeatures\12\TEMPLATE\FEATURES\WSS.ContentMigration.CopyWeb

The examples all demonstrate how to export and import in one go from a Feature. However, in reality, you will more than likely Export from a publishing Farm (using the STSAdm Adapter for SAF) and then do the Import from a Feature. This means that your CMP can then be easily checked into TFS and then triggered as part of a daily build.

Example : A Macro illustrating how to Export List Item(s) from a chosen List.

The example below contains a SAF macro that Exports a List Item (with an ID of ‘1’) from a list called ‘SportsList’ in a Web called ‘http://localhost/sports’. This will then create a CMP package called ‘Exported.cmp’. This CMP can then later be imported into a new web (in a new farm), using Import List Item (see next example).

<?xml version="1.0" encoding="utf-8" ?> 
<objects xmlns="http://www.springframework.net"> 
 
 <!-- Defines the main macro to process --> 
 <object id="MacroToProcess" type="Macro" > 
 <constructor-arg name="id" value="{41C43948-B22C-4acf-B833-00FA3FF537F1}" /> 
 <constructor-arg name="actions"> 
 <list element-type="IAction"> 
 
 <!-- Exports a List Item --> 
 <object name="ExportItems1" type="Action.ExportListItem"> 
 <property name="EntityList" ref="ExportListItemsList"/> 
 </object> 
 </list> 
 </constructor-arg> 
 </object> 
 
 <!-- Holds a list of individual list Items to export --> 
 <object id="ExportListItemsList" type="Entities"> 
 <constructor-arg> 
 <list> 
 <object type="Entity.ListItemExportSettings"> 
 <property name="SiteUrl" value=”http://localhost/Sports /> 
 <property name="ListName" value="SportsList" /> 
 <property name="ListItemId" value="1"/> 
 <property name="ExportSettings"> 
 <object type="Entity.ExportSettings"> 
 <property name="BaseFileName" value="Exported.cmp" /> 
 <property name="FileCompression" value="True" /> 
 <property name="FileLocation" value="c:\Temp\Migration" /> 
 <property name="FileMaxSize" value="100000" /> 
 <property name="OverwriteExistingDataFile" value="True" /> 
 <property name="IncludeSecurity" value="False" /> 
 <property name="IncludeVersions" value="True" /> 
 <property name="LogFilePath" value="c:\Temp\Migration\ExportLog.txt" /> 
 </object> 
 </property> 
 </object> 
 <!--... More Objects to Export here - if needed ...--> 
 </list> 
 </constructor-arg> 
 </object> 
</objects> 
 
 

 

Example : A Macro illustrating how to Import List Items (s) into a destination List.

The example below contains a SAF macro that Imports a set of List Items from a CMP Package called ‘Exported.cmp’ into a list called ‘SportsList’ (contained in a Web called ‘http://IntegrationWeb/DestWeb1’).

<?xml version="1.0" encoding="utf-8" ?> 
<objects xmlns="http://www.springframework.net"> 
 
 <!-- Defines the main macro to process --> 
 <object id="MacroToProcess" type="Macro" > 
 <constructor-arg name="id" value="{41C43948-B22C-4acf-B833-00FA3FF537F1}" /> 
 <constructor-arg name="actions"> 
 <list element-type="IAction"> 
 <!-- Imports the List Item (from above) into a different List--> 
 <object name="ImportItems1" type="Action.ImportListItem"> 
 <property name="EntityList" ref="ImportListItemsList"/> 
 </object> 
 </list> 
 </constructor-arg> 
 </object> 
 
 <!-- Holds a list of items to Import --> 
 <object id="ImportListItemsList" type="Entities"> 
 <constructor-arg> 
 <list> 
 <object type="Entity.ListItemImportSettings"> 
 <property name="SiteUrl" value="http://IntegrationWeb/DestWeb1" /> 
 <property name="ListName" value="SportsList" /> 
 <property name="ImportSettings"> 
 <object type="Entity.ImportSettings"> 
 <property name="BaseFileName" value="Exported.CMP" /> 
 <property name="FileCompression" value="True" /> 
 <property name="FileLocation" value="c:\Temp\Migration" /> 
 <property name="RetainObjectIdentity" value="False" /> 
 <property name="IgnoreWebParts" value="False" /> 
 <property name="IncludeSecurity" value="False" /> 
 <property name="MakeInternalLinksRelative" value="True" /> 
 <property name="LogFilePath" value="c:\Temp\Migration\ImportLog.txt" /> 
 </object> 
 </property> 
 </object> 
 </list> 
 </constructor-arg> 
 </object> 
</objects> 
 
 

 

A couple of Important Points :

  1. The source and destination lists must be schematically identical.
  2. The account who the Macro runs under, must have relevant permissions to both the source and destination list. (Although this can be 2 different users).
  3. All 3 pairs of Actions require SharePoint SP1 as a minimum.
  4. Please feel free to ask any questions here, so that I can help to structure the documentation around your needs.
  • Facebook
  • Twitter
  • DZone It!
  • Digg It!
  • StumbleUpon
  • Technorati
  • Del.icio.us
  • NewsVine
  • Reddit
  • Blinklist
  • Add diigo bookmark

Comments  (5)

  • Dannny Myers 22 Jun

    You mentioned that we can use SAF from STSAdm too. All the examples in the source code are for Features - how do we use these via STSAdm ? I would ideally like to export Lists that our Content Editors populate (on a kind of early publishing environment), then Export the content on a daily basis. Then place the CMP into our source control. Hence, I want to the exporting via STSAdm (not a feature) and potentially import at build time via a Feature (or even STSAdm again).

    Would appreciate a response
    - Danny M,
  • Mark Jones 24 Jun

    Hi Danny

    Sorry for the slight delay in response!

    You are trying to do exactly what I would recommend.

    To export your content into a CMP you are correct to use STSAdm as this will be more than likely be something that you would do many times within a build, and isn't best suited to run from a Feature. STSAdm also doesn't suffer from the 6 minute timeout that a Feature will by default.

    To run any macro via STSAdm is pretty straightforward. The extension takes three arguments :

     - macrofile : path to a valid Macro Xml (containing your Actions)
     - mode : the process you want to run (either "do" or "undo").
     - url : the url to carry the macro out against

    Example :

    stsadm -o saf-run -macrofile c:\macros\ExportSportsList.xml -mode do -url http://localhost

    To import the content, you have a few options. You could either bring it in via STSAdm, or via a feature. The Feature could then be activated by a User, or when a site is created (thats based on a Site Definition). (Give me a shout if you need more info on the latter).

    Incidentally, when we have the web service adapter ready, you will be able to run macros remotely, meaning that you could effectively export content from a list on a remote farm in this instance.

    If the Web Service funtionality is something you would be interested in, I could priortise it to do next in our back log.

    Cheers
    Mark
  • Danny Myers 24 Jun

    Thanks Mark!

    I would imagine that a Web Service for SAF would go a storm out there too!
  • Raj 09 Jul

    The Import List (ImportList) action is throwing the following error:

     

    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)

    I couldn't able to figure out why this is throwing an error. I exported the List data using the Export list Action and getting the above error when I try to import it to the List from the CAB file.

    Any ideas?

  • Mark Jones 09 Jul

    Hi Raj

    Yep, I know why this is. It's an issue that can get thrown by the Content Migration API. Can you check the following :

    1..Your destination list doesn't already have items with the same Ids in it.
    2..You dont have any items (with the same Id's) in the Users Recycle Bin
    3..You don't have any items (with the same Id's) in the Site Collection Recycle Bin.

    Incidentally, this works pretty nicely if you pair it with the "Delete List" which can be instructed to delete list items only by setting the "ListItemsOnly" property to "True".

    Let me know if this solves your problem.
Post a comment!
  1. Formatting options