It all started after a simple migration from SPS2003 to MOSS2007. As you know, sites created under the SPS2003 sites directory are migrated as a new site collection each (!). That is not a desirable situation, and many of us use stsadm to export those sites and import them as subsites (webs) under site directory (see this post for more info).
The Problem here, is that you have to do this manually for each site. This can be really frustrating if you have more than a few sites, So I decided to write a little application that will help me with this annoying chore.
A little quest in MSDN and Google led my to the Microsoft.SharePoint.Deployment namespace.
This namespace includes 2 main classes: SPExport and SPImport.
So I play a little bit with SPExport and get it to export all of the site collections in the "sites" managed path. So far so good.
Now I play a little bit with SPImport and can't get it to work!
The import always fails with this kind of error: "Cannot import site. The exported site is based on the template STS#0 but the destination site is based on the template SPS#0. You can import sites only into sites that are based on same template as the exported site. You can import sites only into sites that are based on same template as the exported site.".
Documentations doesn't have anything about the import operations, So, I turn to the web and find this discussion on TechNet and this article on MSDN. The code on both pages does not work!
"stsadm -o import" worked perfectly, so I used Reflector to analyze it, and hopefully find out what it does that I'm missing.
As it turns out, it creates an event handler that is called when the import starts, and set 2 properties of the SPImportObject class. Those are "TargetParentUrl" and "TargetName", and they are needed in order to create the new subsite. "TargetParentUrl" is the server relative URL that specifies the location where you want the subsite created, and "TargetName" is the URL name of the new site. Because SPImportObject Doesn't expose a public constructor, we have to change the one that is already created.
So in order to get SPImport to work, you will need to add this before you call SPImport.Run():
|
EventHandler<SPDeploymentEventArgs> handler = new EventHandler<SPDeploymentEventArgs>(this.OnStarted); import.Started += handler; \\ Assuming your instance of SPImport is called "import" |
This code will attach the OnStarted method to the Started event of the SPImport operation.
Then, create the OnStarted method to handle the event, and assign values to TargetName and TargetParentUrl:
|
private void OnStarted(object sender, SPDeploymentEventArgs args) { SPImportObjectCollection rootObjects = args.RootObjects; rootObjects[0].TargetParentUrl = sitePath; \\string sitePath = @"/SiteDirectory"; rootObjects[0].TargetName = siteName; \\string siteName = "NewSite"; //Your site will be imported into the newly created http://portal/SiteDirectory/NewSite } |
And That's it. Now you should be able to import sites programmatically. Enjoy!
Note: While searching the web I did find this discussion, that can lead you in the right direction. But it doesn't include any coding instructions, and I felt this issue should be clarified.
Another Note: When I'm finished with this application, I will share it here.