Some people may have read my post from a few days ago regarding the retargetting of the content query web part which was necessary because I had to move a sub-site from one site collection to another. In order to do the move I used the built-in import command. The problem that I sought to address with the retargetting of the content query web part was the result of the import creating new object identifiers for the lists and other such items that were imported. The only thing is that my solution only addressed the symptoms and not the actual problem and it did not address the other similar issues (such as data form web parts which suffered the same issue).
The real problem was with the import itself – internally the built-in import command sets the RetainObjectIdentity property of the SPImportSettings object to false and there is no option that you can pass into the command to override this. This is most unfortunate as this particular property has a profound affect on how objects are imported. If you set this to false then all objects are given a new ID – this is great if your intention is to duplicate a web or list within a given content database but if your intention is to move a web or list then resetting all the object IDs can really mess some things up.
For instance – if you have use the IT Team Workspace template from the Fantastic 40 application templates and attempt to move an instance of that web to another site collection via the export/import commands you will be rather annoyed to find that all of the data form web parts on the main page no longer function. If you attempt to open the web parts in SharePoint Designer to fix them you’ll find that you are unable to. The only solution is to export the web part, change the old IDs to the new IDs and then re-import the web part.
But this headache could have all been avoided if we could have told the import statement to retain the original object identifiers. So, as a solution to this problem I built a new version of the import command called gl-import2. My version functions exactly the same as the built-in version but adds to it the ability to specify whether you wish to retain the original object identifiers. If you do not wish to do this then it will call out to the built-in command thereby only using my custom version if you wish to retain object IDs.
Fortunately I already had most of the code as I had to create it for the gl-importlist command that I created. The additional code I figured out by simply using Reflector to look at what Microsoft was doing with the built-in import command. In this way I was able to make sure that my command preserved all the functionality of the original. The core code is shown below:
The syntax of the command I created can be seen below. With luck Microsoft will realize the benefits of this capability and will add the parameter to the built-in command with the next service pack. Note that I also added the same ability to retain object IDs to my gl-importlist command.
C:\>stsadm -help gl-import2 stsadm -o gl-import2 An improved version of the built-in "import" command. Allows the ability to retain the original object identifiers. Parameters: -url <URL to import to (parent if retainobjectidentity, otherwise full url of target location)> -filename <import file name> [-includeusersecurity] [-haltonwarning] [-haltonfatalerror] [-nologfile] [-updateversions <1-3> 1 - Add new versions to the current file (default) 2 - Overwrite the file and all its versions (delete then insert) 3 - Ignore the file if it exists on the destination] [-nofilecompression] [-quiet] [-retainobjectidentity (the source must not exist in the content database and the url parameter must refer to the parent web)]
Here’s an example of how to import a web into a site collection while maintaining all the original object IDs:
stsadm -o gl-import2 -url "http://intranet/hr" -filename "c:\export.cmp" -includeusersecurity -retainobjectidentity
Update 10/11/2007: A clarification is needed on the impact of the retainobjectidentity. This parameter will affect how the URL is provided. If you set retainobjectidentity then the url must correspond to the targets parent web – a new web site will be created using the name of the exported site (so if the exported site was "http://intranet/test1" and you want the new path to be "http://teamsites/sites/site1/test1" you would specify the url as "http://teamsites/sites/site1" – note that /sites/site1/test1 cannot already exist – don’t use createweb). If you do not specify retainobjectidentity then the url parameter must be the target url (this allows you to specify a different web name) but the target web must already exist with a matching template (use createweb to create the placeholder web). If you wanted to do the same as described above but without retaining the object IDs then you would specify the url as "http://teamsites/sites/site1/test1". Also – I discovered that the retainobjectidentity switch introduces another limitation – it really only works with webs that are not sub-webs of another web (so first level child objects of a site collection). This is a limitation of the deployment API and not my command.