Pages

Tuesday, May 29, 2012

Export Import SharePoint Site using Web Service

Problem:

While working with SharePoint Online – sometimes it is required to take the backup of the site or to export the site to some other environment, but due to no access to SharePoint server, we end up with writing huge code to migrate the site contents to another site using any client object model.
If server side scenario is considered, we have lots of options to perform a simple site export and import operation , like say – use stsadm commands , use Central Administration , use powershell scripts but for SharePoint Online environment what to do? Well here comes web services in picture , how? We will see in details.

Solution:
SharePoint Web services are already there since MOSS 2007, but mostly not used. Here we are going to use the sites.asmx web service to export and import the sites.
Note that before performing these operations using web services – make sure that you have site collection administrator rights on source as well as target site.
I created a Team site as source site and added some sample data to it , say about 4000 documents + 3000 list items with attachments + some content types + some site columns + some lookup columns + some list and content type workflows.

We can use the ExportWeb function given by the sites.asmx web service which takes some parameters as input – let’s see what those are.
  • 1.       jobName: this is the string parameter and can be set to any string , using this name the cmp files will be created. Please make a note that no special characters are allowed here.
  • 2.       webUrl: url of the site which needs to be exported as cmp files.
  • 3.       Datapath: path where all cmp files will be stored (typically a path of the document library on source site)
  • 4.       Includesecurity: as name suggests – Boolean parameter to include security or not
  • 5.       Overwrite: Boolean parameter to overwrite cmp files on save location
  • 6.       cabSize: size of each cmp file , can be set to 2GB max.
  • Export web function returns an integer after completion , but mostly the description is not available for the return types. 
Here it is :

Value
Description
1
Pending: The operation is in progress.
4
InvalidExportUrl: The site specified in the webUrl is not accessible.
5
ExportFileNoAccess: The location specified in the dataPath is not accessible.
6
ExportWebNoAccess: The user does not have the required permissions to execute this operation successfully. The user MUST have the ManageLists and AddListItems permissions in the solution gallery.
7
ExportError: An error other than the errors listed in this table occurred during exporting the site. An example of a condition that would result in this error is if there was no content on the site to export.
8
UploadDataError: The content migration package file is not uploaded to the server successfully. This can occur if the specified path was invalid, read-only, the caller is not authorized to access it, or the file is already open.

ImportWeb:
While importing the web from cmp files using web services – we can use ImportWeb function of sites.asmx web service.

Important part here is – the target site on which import is to be done – should be created using OOB blank site definition. There can be an error while performing the import operation like – the source site is created using template STS#0 and target site is created using STS#1 , - solution to this is – create target site collection without any template – select the select template later option while creating target the site collection.
ImportWeb function take some parameters let’s see what those are
  • 1.       jobName: string parameter , can be set to anything – but no special characters should be included.
  • 2.       webUrl: url of target web.
  • 3.       dataFiles: this is array of string containing url of all cmp files. Example : If there are 10 cmp files in the source location – then dataFiles parameter will be any array having urls of 10 files in ascending order.
  • 4.       logPath: path where log file can be created. This can be passed as null. (typically a url of any document library)
  • 5.       includesecurity: to include security or not
  • 6.       overwrite: overwrite log files.
Similar to ExportWeb function – ImportWeb function also return an interger on completion.
Here are the details

Value
Description
1
Pending: The operation is in progress.
2
GenericError: An error other than the errors listed in this table occurred importing the site.
4
InvalidImportUrl: The site specified in the webUrl is not accessible.
5
ImportFileNoAccess: At least one location specified in dataFiles is not accessible.
6
ImportWebNoAccess: The user has insufficient permission to import to the location specified in webUrl.
8
mportWebNotEmpty: The location specified by webUrl corresponds to an existing site that is not a blank site.
11
LogFileNoAccess: The location specified by logPath is not accessible.

Ok , so after lots of theory – here is the simple console application example which I tried on my environment successfully.

static void Main(string[] args)
{
    string sourcesiteurl = "http://sourcesitecollection/";
    string targetsiteurl = "http://targetblanksitecollection/";
    string svcUrl = "_vti_bin/sites.asmx";

    Sites sites = new Sites();
    NetworkCredential credentials = new NetworkCredential("username", "password", "domain");
    sites.Credentials = credentials;
    sites.Timeout = 600000;

    Console.WriteLine("Choose..1. Export , 2. Import");
    string responce = Console.ReadLine();

    if (responce.Equals("1"))
    {
       sites.Url = string.Format("{0}{1}", sourcesiteurl, svcUrl);
       try
       {
         int result = sites.ExportWeb("MyExportTest", sourcesiteurl, "http://sourcesite/Exports", true, true, true, 1024);
         Console.WriteLine("done with result - " + result.ToString());
       }
       catch (Exception ex)
       {
          Console.WriteLine(ex.Message);
          Console.WriteLine();
          Console.WriteLine(ex.StackTrace);
       }
     }

     else if (responce.Equals("2"))
     {
         sites.Url = string.Format("{0}{1}", targetsiteurl, svcUrl);
         string[] dataFiles = new string[] { "http://sourcesite/Exports/MyExportTest.cmp" };
         
          try
          {
            int result = sites.ImportWeb("MyExportTest", targetsiteurl, dataFiles, null, true, true);
            Console.WriteLine("done with result - " + result.ToString());
          }
          catch (Exception ex)
          {
            Console.WriteLine(ex.Message);
            Console.WriteLine();
            Console.WriteLine(ex.StackTrace);
          }
       }
     Console.ReadLine();
   }



Monday, April 23, 2012

Add ECB Menu to any field in SharePoint porgrammatically

After long research on this - came up with something like this , however there are lots of approaches already available on net which shows you to do the same using SharePoint designer or by creating new column.
Thanks to improved SharePoint 2010 APIs which gives the SPField.ListItemMenu property , but one thing to note here is setting this property to true does not reflect the changes , before setting this property - MSDN documentation says that you need to set the SPField.ListItemMenuAllowed to Required.


try
{
   SPContext.Current.Web.AllowUnsafeUpdates = true;

   SPList list = SPContext.Current.Web.Lists.TryGetList("Cities");
   SPField countryField = list.Fields.GetField("Country");
   if (countryField.ListItemMenuAllowed == SPField.ListItemMenuState.Prohibited || countryField.ListItemMenuAllowed == SPField.ListItemMenuState.Allowed)
   {
       countryField.ListItemMenuAllowed = SPField.ListItemMenuState.Required;
   }
    countryField.ListItemMenu = true;
    countryField.Update();
    list.Update();
    SPContext.Current.Web.Update();

    SPContext.Current.Web.AllowUnsafeUpdates = false;

 }
 catch (Exception ex)
 {
    this.Controls.Add(new LiteralControl("Error: " + ex.Message));
 }

Hope this helps someone.

Friday, March 9, 2012

Outlook 2010 AddIn - Create new meeting request and mails programmatically

Few days back , questioned was thrown at me like - hey dude , have you ever tried extending ribbon in outlook? and my answer at that point was 'No'. then next question was - is it possible to have some buttons in the ribbon which will allow you to create new meeting request and mails with predefined data and recipients?

Question did sound interesting to me , and that immediately taken me in front of machine. I opened up VS 2010 to see what can be done.
It is easy to extend ribbon of Office applications using VS 2010 , as it gives you the project template.
I will not cover up how to create new ribbon and add buttons on it but here is what I learned on that evening - how to create new meeting request and new mails with predefined contents.
Just added two buttons on my custom ribbon , and added code behind of custom ribbon and buttons


private Application m_outlookApp;
private Explorer m_outlookActiveWindow;

  • To create new mail programmatically
 
try
{
    m_outlookApp = Globals.ThisAddIn.Application;
    m_outlookActiveWindow = m_outlookApp.ActiveExplorer();

    MailItem mailItem = m_outlookApp.CreateItem(OlItemType.olMailItem) as MailItem;

    if (mailItem != null)
    {
       mailItem.Body = "Add Your Contents Here..";
       mailItem.Subject = "Add Appointment Subject Here..";
       mailItem.To = "target.user@smtp.com";
       mailItem.Save();
       mailItem.Display(true);
       Marshal.ReleaseComObject(mailItem);
    }
 }
 catch (System.Exception ex)
 {
       System.Windows.Forms.MessageBox.Show("Error: " + ex.Message);
 }

  • To create new meeting request programmatically


try
{
   m_outlookApp = Globals.ThisAddIn.Application;
   m_outlookActiveWindow = m_outlookApp.ActiveExplorer();

   AppointmentItem appItem = m_outlookApp.CreateItem(OlItemType.olAppointmentItem) as AppointmentItem;

   if (appItem != null)
   {
     appItem.Body = "Add Your Contents Here..";
     appItem.Subject = "Add Appointment Subject Here..";
     appItem.RequiredAttendees = "target.user1@smtp.com;target.user2@smtp.com";
     appItem.OptionalAttendees = "optional.user1@smtp.com";
     appItem.Start = DateTime.Now.AddHours(1);
     appItem.End = DateTime.Now.AddHours(2);
     appItem.Save();
     appItem.Display(true);
     Marshal.ReleaseComObject(appItem);
   }
 }
 catch (System.Exception ex)
 {
     System.Windows.Forms.MessageBox.Show("Error: " + ex.Message);
 }


References:
http://blogs.msdn.com/b/mcsuksoldev/archive/2010/10/01/building-and-deploying-an-outlook-2010-add-in-part-1-of-2.aspx
http://www.add-in-express.com/creating-addins-blog/2011/11/04/outlook-create-appointment-item/
http://msdn.microsoft.com/en-us/library/bb612741.aspx


Working with custom user profile properties programmatically

This one is just to share how can we get the values of custom properties in user profiles in SharePoint 2010. actually this was the outcome of a quick POC while answering on MSDN SharePoint forums. so thought to share as this may help someone.

I have created a custom user profile property of type string and internal name is set to PrefferedColor while display name is - Preffered Color.
Then a simple web part which reads this custom user profile property.

All you need to do is Include references of following assemblies

Microsoft.Office.Server;
Microsoft.Office.Server.UserProfiles;


public class ShowPropertyWp : WebPart
{
  private string m_propertyInternalName = "PrefferedColor";
  private string m_propertyDisplayName = "Preffered Color";
  private string color;

  protected override void CreateChildControls()
  {
    try
    {
      Guid siteId = SPContext.Current.Site.ID;
      Guid webId = SPContext.Current.Web.ID;
      using (SPSite site = new SPSite(siteId))
      {
        SPServiceContext serviceContext = SPServiceContext.GetContext(site);
        UserProfileManager upm = new UserProfileManager(serviceContext);

        if (upm != null)
        {

             UserProfile up = upm.GetUserProfile("domain\\user");
             if (up != null)
             {
                color = up[m_propertyInternalName].Value.ToString();

                color = up[m_propertyDisplayName].Value.ToString(); // This will give an error.
             }


         }
      }

      if (!string.IsNullOrEmpty(color))
      {
         this.Controls.Add(new LiteralControl("You Have Preffered Color - " + color));
      }
      else
      {
         this.Controls.Add(new LiteralControl("You have not selected any preffered color"));
   }
  }
  catch (Exception ex)
  {
     this.Controls.Add(new LiteralControl("Error: " + ex.Message));
  }
 }
}


Tuesday, March 6, 2012

Visual Studio 2011 Beta - Creating Site Definition

This is just to quickly share some views on how to create a custom site definition using Visual Studio 2011 Beta.

This is a great enhancement for someone like me who really remembered all XML tags which are in Onet.xml / Site Definition. Now you dont have to do this manually at all , just create a solution and add new site definition in it using UI. How ? here is the answer.

I have created a sample solution using VS 2011 beta and adding new SharePoint site definition to it.



I have just added a new site definition to the project and given name as TestSiteDefinition.

Once you are done with these clicks , take a look at the solution explorer and see which are the files which are added. VS adds all files related to site definition like Onet.xml , webtemp_*.xml and a default page automatically , which we used to write and add manually for MOSS 2007 and SharePoint 2010 using previous versions of VS.




Lets take a look at each file -

1. default.aspx - This is a standard SharePoint page with default.master as master page and has only   twocontent controls on it which refers to the PlaceHolders from maste page - one is PlaceHolderPageTitle and other is PlaceHolderMain. You can now edit the file and add your customizations on it.

2. Onet.xml - This file contains all elements like Project, NavBars,Configuration and Modules. By default no feature is added in the SiteFeatures and WebFeatures elements of default configuration ID 0 , and a module is added whcih points to the default.aspx page. but wondering why ListTemplates and DocumentTemplate elements are missing here.
You can read more on onet.xml here

3. webtemp_TestSiteDefinition.xml - This file contains Template element. custom template is given ID of 10000 by default and display category is SharePoint Customizations by default.

Now I will just right click the solution and deploy this custom site definition and see what happens - and here is the output




Conclusion : Now with the new version of VS it is much easy to create site definitions and get started with your customizations.

Monday, March 5, 2012

Visual Studio 2011 Beta - What's new for SharePoint 2010

Now here it comes ,  It's 00:20 AM and I just installed VS 2011 beta version on my SP Virtual machine. I know that this is bit late to install this beta since MS has released it quite few days back , but I believe in better late than never so posting this just to share some thoughts on whats new available in beta for SharePoint developers.

Before going forward I would like to make a point here - I really liked the installation screen while installing VS 2011 , thought it took more than 30 minutes but doesn't matter. you can also try to see the innovative (because I seen this first time while installing any MS product) installation UI. you can download the beta copy of VS 2011 at this - http://www.microsoft.com/visualstudio/11/en-us

What's new for SharePoint?

Here is the screenshot which shows you the list of available items while adding to SharePoint 2010 project type


As you can see in image above , there are few options which are new in VS 2011 beta.

No More pain to work with schema.xml of list definition

Lets see the option to create List using new option.
When you select the list option and select add - VS  2011 gives you the screen to select the template for your list , by default it gives you to choose from the default blank list , document library and task list template.
However it also gives you control to reuse the existing list templates which are already present on your target site. (the site to which you will be deploying the solution).


Next , after selecting the list template and display name of your list , click finish and here comes the interesting part.

Thought VS adds the same structure in the solution explorer like we used to see in VS 2010 , the List Definition XML , List Instance and a feature to package and deploy this as single unit , but now with VS 2011 there is significant improvement in the rendering of complex structure of List Definition's schema.xml , VS 2011 shows you in well formatted UI where you can really play around adding new list columns , adding and setting default content types of list as well as work efficiently with list views.



As you can in the Image above , there is systematic way to display the columns , views and list. in columns tab you can see the available list columns and here you can add the list columns directly just with the help of few clicks , there is also a content type button defined where you can associate various content types with the list , like -


Now in the Views section - you can define the views as well as view settings in UI like


and finally in the list tab you can play around list instance's properties like List URL  , List description like -



and you are done , just right click the solution and deploy , you will have your list created with all defined settings.

In part 2 of this post , will explore some more new features.