Tuesday, September 29, 2009

SharePoint List Export/Import Functinality.

Hello Friends,
This is laxmikant again.
Thank for your last reply.

Now i m gone discuss with you on another well known topic "SharePoint List Export/Import Functinality". So lets start.
First off all might be you all know we have some inbuilt options for Import/Export for List from one server to another. If you don't know lets me tell you.

WSS and MOSS use this API at various different places:

  • Content Deployment
  • STSADM -o export and import
  • Copy/Move operations in Site Manager
  • Variations
  • MCMS 2002 database migration to MOSS 2007


Assembly: Microsoft.SharePoint.dll
Namespace: Microsoft.SharePoint.Deployment

Important Objects:

  • SPExport - controls the Export process
  • SPExportSettings - used to configure the export process
  • SPExportObject - defines which objects need to be exported
  • SPImport - controls the import process
  • SPImportSettings - used to configure the import process

Providing some real world samples for export

To demonstrate how powerful the Content Deployment and Migration API is I will now provide some real world examples:

  1. Export a complete Site Collection
  2. Export a specific sub web
  3. Exporting other elements like lists, document libraries, list items or documents from a document library
  4. Exporting using compression
  5. Incremental Export

The examples below assume that the source site collection is on the local server on port 2000.

Lets start with a scenario that can also be covered by using stsadm.exe:


1) Export a complete Site Collection


Actually there are two different methods to export a complete site collection.

Method 1)

SPExportSettings settings = new SPExportSettings();
settings.SiteUrl = "http://localhost:2000";
settings.ExportMethod = SPExportMethodType.ExportAll;
settings.FileLocation = @"c:\export";
settings.FileCompression = false;
settings.CommandLineVerbose = true;
SPExport export = new SPExport(settings);
export.Run();

So what did we actually do here? First we created a SPExportSettings object to define the general configuration settings for the export we would like to perform. As we did not select a specific object to export the configured site collection will be selected for export. Then we created the SPExport object based on the configured settings and started the export by calling the Run method.

Here is a short explanation about the settings being used in the code above:

  • SiteUrl - this property defines which site collection the export should use. All objects being exported always have to be in the same site collection. The Content Deployment and Migration API cannot access items in different site collections in a single operation.
  • ExportMethod - this property allows to define whether to perform an incremental export (value = ExportChanges) or everything (value = ExportAll). Be aware that ExportChanges would require to provide an Export Change Token in a separate property.
  • FileLocation - this property defines where to store the exported content. The value should point to be an empty directory. If the directory does not exist it will be created during export. If file compression is being used, then only the compressed files will be stored on this location. The uncompressed files will be stored in the directory identified by the value of the system wide TMP environment variable. So you need to ensure that the directory the TMP environment variable points to also needs to have sufficient space available.
  • FileCompression - this property defines whether the content should be compressed into a CAB file. If you need to archive the exported content or need to transfer it to a different machine you should choose to compress. If you only export the content to import it afterwards using code on the same machine and don't need to archive (e.g. a copy or move operation) then you should decide to disable the compression as this is significantly quicker.
  • CommandLineVerbose - this parameter allows to control if the API should provide some verbose output. If you have ever seen the generated output when running STSADM -o export: this is exactly the flag the generates this output. If the value is false no output is generated.

Method 2)

SPSite site = new SPSite("http://localhost:2000");

SPExportObject exportObject = new SPExportObject();
exportObject.Id = site.ID;
exportObject.Type = SPDeploymentObjectType.Site;

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

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

site.Dispose();

What did we actually do here? In this method we explicitly add a specific object to the ExportObjects collection - the SPSite object defining the site collection. This leads to the same result as the first method where the SPSite object was implicitly selected as no explicit object was selected for export.

Here is a short explanation about the settings being used in the code above:

  • SPExportObject.Id - GUID of the object that should be exported
  • SPExportObject.Type - The type of the object to be exported. This can be one of the following:
    • Site = SPSite object (the site collection)
    • Web = SPWeb object (often referred to as site)
    • List = SPList object
    • File = SPFile object
    • Folder = SPFolder object
    • ListItem = SPListItem object
  • for the other properties see Method 1


2) Export a specific sub web


The code to export a specific subweb is very similar to the code used in method 2 to export the complete site collection:

SPSite site = new SPSite("http://localhost:2000");

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

SPExportObject exportObject = new SPExportObject();
exportObject.Id = web.ID;
exportObject.IncludeDescendants = SPIncludeDescendants.All;
exportObject.Type = SPDeploymentObjectType.Web;

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

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

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

Be aware that when exporting a specific sub web using the method above might also export objects outside the specific subweb as not only the objects in the sub web are exported but also dependent objects like images referenced in pages by this sub web and the master page assigned to the sub web.

Whether such dependent objects should be exported or not can be controlled by the ExcludeDependencies property of the SPExportSettings. Whether child objects of an object are exported can be controlled using the IncludeDecendents property of the SPExportObject object:

  • ExcludeDependencies - This property controls whether to export dependent objects like referenced images, master pages or page layouts. If it is unclear if the dependent objects are already in the destination database you should export the dependent objects as well to prevent problems.
  • IncludeDescendants - This property controls whether to export child objects of the selected objects (like sub webs, lists, list items) or only the selected object. Possible values are None (only the object is exported), Content (List and libraries of a web will be exported but not sub webs) and All (all child content is exported)


3) Exporting other elements like lists, document libraries, list items or documents from a document library

Other objects or containers can be exported in the same way by adding them to the ExportObjects collection.

SPSite site = new SPSite("http://localhost:2000");
SPWeb web = site.OpenWeb("/SomeWeb");
SPList list = web.Lists["MyList"];
SPListItem listItem = list.Items[0]; // select the first list item

SPExportObject exportObject = new SPExportObject();
exportObject.Id = list.ID;
exportObject.Type = SPDeploymentObjectType.List;

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

...

Exporting document libraries can be done using the same code as exporting a list as internally a document library is implemented as a list. And a document in a document library can be exported using the same method as exporting any other list item. The SPFile object of the document will automatically be automatically exported together with the SPListItem object.


4) Exporting using compression

When exporting using compression additional settings in the SPExportSettings object need to be adjusted:

SPExportSettings settings = new SPExportSettings();
settings.FileLocation = @"c:\export";
settings.FileCompression = true;
settings.FileMaxSize = 10; // defines the maximum filesize as 10 MB
settings.BaseFileName = "ExportedItems.cmp";
...

Here is an explanation about the two properties:

  • FileCompression - this property defines whether the content should be compressed into a CAB file. If you need to archive the exported content or need to transfer it to a different machine you should choose to compress. If you only export the content to import it afterwards using code on the same machine and don't need to archive (e.g. a copy or move operation) then you should decide to disable the compression as this is significantly quicker.
  • FileLocation - this property defines where to place the export files. If compression is used it defines the location of the generated compressed content migration pack.
  • FileMaxSize - this property defines the maximum size of the created content migration pack.
  • BaseFileName - this property is only used if compression is enabled. It defines the name of the compressed content migration pack file. The default extension (if not specified) is ".cmp". If the size of FileMaxSize is exceeded a new file is created with the BaseFileName and an integer number. E.g. with the above configuration the next file would be ExportedItems1.cmp


5) Incremental Export
If incremental export should be done it is required to save the Change Token of the last full or incremental export. This change token needs then be provided in the ExportSettings to allow the Content Deployment and Migration API to determine which items have changed.
So after a previous export the change token can be retrieved using the following code:
SPExportSettings settings = new SPExportSettings();
...
SPExport export = new SPExport(settings);
export.Run();
string ChangeToken = settings.CurrentChangeToken;

Explanation:

  • CurrentChangeToken - this property is a read-only parameter populated during export. It contains the Change Token right after the export. So doing an incremental export providing this change token in the future will export all items that have been created, changed or deleted in the configured scope after the change token was generated.

To start an incremental export using this change token would then be done using the following code:

SPExportSettings settings = new SPExportSettings();
settings.ExportMethod = SPExportMethodType.ExportChanges;
settings.ExportChangeToken = oldChangeToken;
...

Explanation:

  • ExportMethod - this property allows to define whether to perform an incremental export (value = ExportChanges) or everything (value = ExportAll).
  • ExportChangeToken - this property defines which items to export when using incremental deployment. the incremental export will only export items that have been created, changed or deleted in the configured scope after the change token was generated.

Providing some real world samples for import

After we managed to export content in part 2 lets now focus on the importing side. Import actually has two different ways to work:

  • Import by preserving the object identity and location
  • Import without preserving the object identity

The first method is used in the Content Deployment function available through the Central administration page. The second method is used by STSADM -o import and when doing the Copy/Move operations in Site Manager. The first method is similar to the import method used in CMS 2002: the imported objects will get the same GUIDs as on the source system. The second method on the other hand allows to import items at different places in the site collection hierarchy and can therefore be used for copy operations.

To demonstrate how powerful the Content Deployment and Migration API is in this area I will again provide some real world examples.

  1. Import by preserving the object identity
  2. Change the Parent of the imported objects during Import

The examples below assume that the destination site collection is on the local server on port 2001.


1) Import with preserving the object identity

A pre-requesit of this method is that the parents of all imported objects need to be in the destination database. So it is not possible to use this method to import into a site collection with a different structure. Usually it means you will use this in classic staging scenarios where you have an authoring farm, a staging farm and a production farm. The content is initially created on the authoring farm and then deployed to the staging farm.

For this method it doesn't matter if the package only contains a single list item or a web or a complete site collection. It also doesn't matter if the export has been done using incremental deployment or using full deployment. As all parents for the objects in the package need to be in the destination database the import engine will correctly import the items.

If you have different site collections and need to exchange data between these (e.g. copy a document library from the site collection of http://www.company1.com/ to the site collection of http://www.company2.com/ you need to use the method without preserving the object identity.

SPImportSettings settings = new SPImportSettings();
settings.SiteUrl = "http://localhost:2001";
settings.FileLocation = @"c:\export";
settings.FileCompression = false;
settings.RetainObjectIdentity = true;

SPImport import = new SPImport(settings);

import.Run();

Similar to the export process we first create an object to configure the import. This is done by using the SPImportSettings method.

Here is a short explanation about the settings I used to perform the import:

  • SiteUrl - this is the Url to the destination site collection the import process will use.
  • FileLocation - this is the directory holding the data that needs to be imported
  • FileCompression - this defines whether the exported data is available in compressed or uncompressed format
  • RetainObjectIdentity - this defines whether to preserve the object identity during import or whether not to preserve the identiy. If the value is true the identity of the objects is preserved. Means Guid and Url of the imported items will be the same as on the exporting server. Be aware that this means that the parent objects of all imported need to be available in the destination database. If the value is false the objects will get a new generated Guid during import and it will be possible to control the parent of the imported root objects during import. We will cover this later.


2) Change the Parent of the imported objects during Import

Let's assume we have exported a list from a source site collection using the steps described in point 3 of part 2. And now we would like to import the list into a different web in the destination site collection. It doesn't matter if the destination site collection is the same site collection as the source or if it is in the same database as the source site collection. It also doesn't matter if the destination site collection is in the same or a different farm as the source site collection.

If you export an item from a database (e.g. a list) without exporting it's parent, then the exported item will become orphaned in the package. A package can contain multiple different orphaned objects (e.g. if you export multiple different lists or list items).

The import method allows us to define a new parent for each orphaned object in the export package. Means if you selected web A to be exported and web B where web B is a sub web of web A then you can only change the parent of web A. The parent of web B will always be web A as web B is not orphaned in the export package.

There are actually two methods that can be used to assign a new parent to orphaned objects:

Method 1 - all orphaned objects should be imported into the same sub web

This method will only work if all items need to be added to the same sub web. E.g. if you have exported a couple of lists and document libraries (even from different source webs) and now would like to import them into the same sub web.

SPImportSettings settings = new SPImportSettings();
settings.SiteUrl = "http://localhost:2001";
settings.WebUrl = "http://localhost:2001/MyDestWeb";
settings.FileLocation = @"c:\export";
settings.FileCompression = false;
settings.RetainObjectIdentity = false;

SPImport import = new SPImport(settings);
import.Run();

There are two important settings that are required to get this working:

  • WebUrl - this property defines the web that will be used as the new parent for all orphaned objects in the export package. This method (e.g.) cannot be used if the package contains orphaned documents as a web cannot be the parent of a document. The parent of a document needs to be a list or a folder.
  • RetainObjectIdentity - this defines whether to preserve the object identity during import or whether not to preserve the identity. If the value is false the objects will get a new generated Guid during import and it will be possible to assign a new parent to the imported orphaned objects.

Method 2 - assign an individual parent to each orphaned object

This method is more flexible than Method 1 but also requires a little bit more coding. Here it will be required to intercept the import process to assign a new parent to each orphaned object after the import process has gathered the list of orphaned objects from the import package.

This can be done using a custom event handler:

static void OnImportStarted(object sender, SPDeploymentEventArgs args)
{
SPSite site = new SPSite("http://localhost:2001");
SPWeb web = site.RootWeb;

SPImportObjectCollection rootObjects = args.RootObjects;
foreach (SPImportObject io in rootObjects)
{
io.TargetParentUrl = web.Url;
}

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

The event handler above does such a "re-parenting" of all orphaned objects which are provided in the RootObjects collection of the event arguments. In the sample above we do actually the same as in the sample provided in Method 1: we assign a fixed web as the new parent of all objects. But you can easily extend the logic in this event handler to (e.g.) assign a different parent based on the object type:

static void OnImportStarted(object sender, SPDeploymentEventArgs args)
{
SPSite site = new SPSite("http://localhost:2001");
SPWeb web = site.RootWeb;
SPList list = web.Lists["MyDocLib"];

SPImportObjectCollection rootObjects = args.RootObjects;
foreach (SPImportObject io in rootObjects)
{
if (io.Type == SPDeploymentObjectType.ListItem)
{
io.TargetParentUrl = list.RootFolder.ServerRelativeUrl;
}
if (io.Type == SPDeploymentObjectType.List)
{
io.TargetParentUrl = web.Url;
}
...

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

As you can see the eventhandler can be extended pretty easily. Beside looking on the Object type you could also look at the original TargetParentUrl to see where the source was located and include this in your "routing" logic. Now we need to see how we can hookup this event handler with the import process. This can be done as follows:

static void ImportDocLibItem()
{
SPImportSettings settings = new SPImportSettings();
settings.SiteUrl = "http://localhost:2001";
settings.FileLocation = @"c:\deployment5";
settings.FileCompression = false;
settings.RetainObjectIdentity = false;

SPImport import = new SPImport(settings);

EventHandler eventHandler = new EventHandler(OnImportStarted);
import.Started += eventHandler;

import.Run();
}

As you can see you need to register the event handler with the import class before starting the import process.

There are a couple more event handlers that can be registered during import which are explained in more details on MSDN:
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.deployment.spimport_events.aspx

Similar events can also be registered for export if required:
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.deployment.spexport_events.aspx


3) Importing using compression

When importing using compression additional settings in the SPImportSettings object need to be adjusted:

SPExportSettings settings = new SPExportSettings();
settings.FileLocation = @"c:\export";
settings.FileCompression = true;
settings.BaseFileName = "ExportedItems.cmp";
...

Here is an explanation about the two properties:

  • FileCompression - this property defines whether the content is available as a CAB file or in uncompressed format.
  • FileLocation - this property defines where the export files can be found. If compression is used it defines the location of the compressed content migration pack.
  • BaseFileName - this property is only used if compression is enabled. It defines the name of the compressed content migration pack file. The default extension (if not specified) is ".cmp".

In Part 4 I will cover specific scenarios like adjusting links in move scenarios. E.g. if an image is moved to a new location you would need to adjust the links in all pages that reference this image.



How to Cutomise SharePoint TaskList

Hello friends,
now i m gone discuss with you on well know topic of SharePoint Site List Item Edit Mode. Whenever user of site edit a listItem. As soon as he edit the item ans mark it as "Completed".
We need to make that item as read only. So further in future nobody can re-edit it. For that i have created a small Costume Activity Using VS.Net 2008. Which further install in SPD. So we can create a workflow to use that.
We are working on List so we need a object of task list, then listItem too. So we know some basic about SPD. Normally like in Workflow we don't have the object like "WorkFlowProperties" in Workflows created in in .net. we have another object for SPD, named as "DependencyProperty ". In details u can understand from code only.
Here is code snapshot in costume activity.


public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(ListItemEditModeDisable));
public static DependencyProperty ItemURLProperty = DependencyProperty.Register("ItemURL", typeof(string), typeof(ListItemEditModeDisable));
---------
SPListItem item = __Context.Web.GetListItem(ItemURL);
string username = item["Assigned To"].ToString();
int no = username.LastIndexOf('#');
no++;
username = username.Substring(no);
SPUser user = __Context.Web.AllUsers[username];

SPGroup newGroup = user.Groups[0];
SPRoleAssignment roleass = new SPRoleAssignment((SPPrincipal)newGroup);
SPRoleDefinition roldef = __Context.Web.RoleDefinitions.GetByType(SPRoleType.Reader);

__Context.Web.AllowUnsafeUpdates = true;

if (item.HasPublishedVersion)
{
item.BreakRoleInheritance(false);
__Context.Web.AllowUnsafeUpdates = true;

}

roleass.RoleDefinitionBindings.Add(roldef);
item.RoleAssignments.Add(roleass);

After You created this costume activity. U need to deploy this in SPD. Just create a workflow for all lists on itemEdited Event. And you have done.
Thanks