Monday, May 21, 2012

How to Migrate SharePoint 2007 to Office 365 Standard Using Native Web Service and CSOM

This post talks about:

1) How to migrate from SharePoint 2007 to Office 365 Standard with native web service and CSOM
2) Issues you would face during the migration and alternatives

To migrate to Office-365 – S using NWS you would have to either write your own tool to pump the content or use migration tools available in market. Writing your own tool would be time consuming and there are tools available in the market to do so.

Let me talk about issues first and then I will list down the steps to do the migration activity.

Issues
Custom web parts related issues
1) Any custom coded web part won’t be migrated by migration tools. You will have to package your web parts as WSPs and deploy as Sandbox solution.
2) Since SharePoint execution model in O365-S is sandboxed, you will have to convert all your custom web parts to be runnable in Sandboxed environment. Sandbox is a restricted execution model so you will have to look for alternatives for features which are restricted. Below are some of the restrictions and alternatives
    1. Response.Redirect doesn’t work – Use client side redirection. For any conditional redirection from server code, use flags and override “Render” method to inject jQuery to do redirection on document ready event
    2. Run with elevated privileges won’t work – if you are writing to some list in your code make sure to give all users proper permissions on the list and your code would work.
    3. ASP.Net client side validations won’t work – use jQuery or javascript to do client side validations
    4. File I/O related operations won’t work – like export to excel or PDF won’t work the way it is generally coded, so use SPFile.SaveBinary to write into a document library and redirect user to the link of the created file.
    5. Will add more limitations and alternatives later.
Custom master pages, layouts and content types
1) Any custom master page, page layouts won’t be migrated by migration tools. So you should deploy these master pages and layouts as WSP solutions. Don’t forget to convert your 2007 master page to 2010 based master page, follow this article “http://msdn.microsoft.com/en-us/library/ee539981.aspx”.
2) Content types will get migrated by migration tools but content type GUID will change and as a result your layouts won’t work referring to old GUID. Solution is to deploy content type also using WSP to retain GUID.
Application pages
3) Application pages are not supported, so convert your application pages to Sandboxed Visual Web Part and provision site pages hosting these web parts.
User profiles
1) UserProfileManager and AudienceManager are not available in Sandbox so to fetch user profile properties use a hidden list called “SiteUserInfoList”. This list has a minimal set of user profile properties synchronised to it. If you need to synchronize more properties just go to UPSA administration and check if the property you want to synchronised is replicable or not.
External content types and integration
1) O365 E3 plan supports BCS for external integration. However in E1 plan BCS is not available, here you expose your external system as a WCF and consume the WCF in Sandbox Visual Web Part using jQuery AJAX and JSONP. The WCF can be anonymous and authenticated as well using both NTLM/Kerberos.
Exception handling and logging
1) Exceptions cannot be logged to ULS. However you can log your exceptions to a custom list and the list can be cleared periodically. But one should try to write exception proof code as much as possible cause each exception raised will increase your resource usage and if your daily quota passes your site will come down until next day.
Deployment
1) Solutions can be easily uploaded as user solutions in Solution gallery. Content can be created/edited using client side object model also.
Timer jobs
1) Timer jobs are not available.
Feature and EventReceivers
1) Both are available.
Data export issues
With SharePoint Native Web Services to import and export data there would be limitations in terms what all can you do. Below are details:
1) If you migrate your lists with any migration tool, your list GUID will change, as a result your code, OOB web parts will break. So fix your code and fix web parts after migration.
2) List item Ids will also change.
3) Migrate your lists and libraries before your migrate your site pages, so that when the list is referenced from your web part during page migration, it does not break.
4) Content migration will not be fast, so plan accordingly.
5) To maintain document metadata (like CreatedBy, ModifiedBy etc), you will have to map all on premise users to corresponding Office-365 users. If you don’t these fields will have credentials of logged-in user under which you created connection to SharePoint Online site collection.
6) Migration tools provide you to map the on-premise users to O365 users.
7) Blog sites will be migrated but post to comments mapping will be lost,so write your own tool to migrate blog sites.
8) Page layout URL field of Pages library for migrated pages will refer to source layout URL, write an admin tool to fix it. Basically they migrate the fields as it is without fixing the layout URL to refer to the new URL.
9) Make sure to publish and approve all master pages and layouts otherwise the tool won’t be able to load them and continue to throw exceptions during migrations.
10) Lists and libraries will be migrated but lookup column associations will break, you will have to manually or by some tool fix the associations.
Migration Steps
Planning and Approach
  1. Dev & test environment
    • In O365-S you start your information architecture creation from site collection onwards. So you can use different site collections as your development and test environment. The catch here is that your URL will be changed per site collection so make sure to do the following:
      • Use relative paths in CSS/JS/C#.
      • Use a custom configuration list to store any URL if you need to, so that you can change it when you deploy to different site collections.
    • Map your on-premise site collections to online site collection
  2. Configure ADFS for single sign on using Smart Links. “http://community.office365.com/en-us/w/sso/using-smart-links-or-idp-initiated-authentication-with-office-365.aspx?Sort=MostRecent&PageIndex=1”
Build
  1. Setup solutions and WSPs
  2. Convert your custom web parts and
    application pages to web parts and be Sandbox compatible
  3. Created required site pages.
  4. Create WSP packages.
Migration Steps
  1. Create your information architecture (site collections, sites, lists etc.). Sub-sites, lists can be created using feature receivers and CSOM.
  2. Deploy WSPs
  3. Publish and approve master pages,layouts.
  4. Migrate lists and libraries. For each migration step the tools allow to generate a PowerShell script. So for each successful migration generate a PoweShell, if you want to do scripted migration later just by changing the URLs.
  5. As you migrate lists and libraries you will be able to migrate versioning, item level permissions, OOB web parts etc.
  6. List views won’t be migrated, so write a tool using CSOM to create list views and run it once list migration is over.
  7. Migrate pages library.
  8. Run tool to migrate blog sites if you have.
  9. Run admin web part to fix page layout URLs.
  10. Fix your ListViewWebParts and other webparts which rely on list GUIDs, cause list GUID is changed.
  11. Sniff your pages, fix UI issues.
  12. Migration done :).

Sunday, March 18, 2012

jQuery Based Tab Control for ASP.Net

This post talks about creating a jQuery based tab control that allows creating tabbed user interfaces easily. Developer can programmatically add, remove, and reorder the tabs. It saves developer from comprehending the jQuery API in order to create tabbed interface. Using this control the developer avoids plumbing required to get the jQuery based tab interface going. The tab control that we will create will allow to keep form fields also in the tab. The tab control will have following features :

Multiple TabsLets developer to add as many tabs as required by stacking tabs in multiple rows. 

Wizard CreationLets developer create a wizard like data entry control. Once the form is submitted and validated successfully, only final tab in the wizard will be enabled. All previous tabs are rendered inactive. 

Integrated Date PickerLets developer specify which text boxes to associate a jQuery date picker with. 

All Supported Locale for Date PickerLets developer specify in which locale to render the jQuery date picker. 

ASP.Net ValidationsSupports both client and server ASP.Net validations. 

Navigation ButtonsLets developer to add client side buttons to navigate back and forth on tabs. 

Validation On NavigationLets developer to do client side validations when tab selection is changed. 

Application Frameworks.Net 3.5, ASP.Net 3.5 and jQuery 1.5.1 and jQueryUI 1.8.1. 

The tab control renders all the tabs using jquery UI API. Each tab is an ASP.Net custom control (ASCX). Tab controls (ASCX) are housed in a wrapper control called GDTabContainer. This wrapper control is responsible for loading all the child controls and rendering the tab markup with the help of a MarkupHelper class. GDTabContainer in turn is added to an ASP.Net PlaceHolder control on the page. Tab properties are stored in a class called GDTabDetails which has following properties as depicted below:
Project's source is available for download at Codeplex here.
 How is the markup generated 
As we know that jQuery expects certain markup (unordered list as tab links and stacked divisions as tabs) and script in order to render division elements as tabs, associate jQuery date picker with text boxes. I generate this markup/scripts by processing the information stored in the GDTabContainer class.  I have overridden the 'Render' method of the page to control markup generation. In the overridden method I do following steps to generate the markup:

  • Fetch the ASP.Net generated control name from control collection and update the name in the list of      GDTabDetails class, so that MarkupHelper class uses these generated names in jQuery selectors, just so that selectors work faster on client.
  • Call the GetjQuery method of MarkupHelper class to render necessary jQuery script to initialize the tabs and datepicker on the document.ready event on client.
  • Render the unordered list that makes up the tab links.
  • Iterate over the list of GDTabDetails class and render tab division tags along with corresponding custom control markup by calling 'RenderContol' on each control. 
How to use
To use the control do following steps:
  • Include GDTabContainer.ascx and its code behind in your project.
  • Include following jQuery framework files (CSS/JS) in your page or master page.

Last two scripts are locale specific; include only the script for the locale you are developing your application in.
  • Initialize tab information like below in OnInit event of your page like below. In this step you simply specify which control (ASCX) will be shown on which tab, identity of the <div> that will hold the control’s rendered markup etc.
  • Initialize the GDTabContainer control in OnInit event of your page like below.


Notice that we just initialized the TabInformation property of the GDTabContainer with the ‘tabDetails’ list which we populated in previous step.

This is all that is required to get the tabbed interface going. After rendering the sample included looks like below: