Friday, December 28, 2012

Content Deployment Feature in SharePoint 2010

Content deployment feature helps deploying content from a source site collection to a destination site collection. More details on MSDN are here. Since this feature was giving me (still does) so many errors in my attempt to use it, thought of blogging my approach.

Here I’m trying to deploy content from http://dered-ca:40921 site collection to http://dered-qa:2222 site collection (dered-ca, dered-qa are two different servers).

Configuration in the destination server:
1. Create new web application and create a site collection without selecting a template.


2. Update new web application with custom code and features by deploying all WSPs.

3. Go to Central Administrator –> General Application Settings –> ‘Configure content deployment’ under ‘Content Deployment’ and select options as below



Configuration in the source server:
1. Go to Central Administrator -> General Application Settings -> Configure content deployment paths and jobs.

2. Select ‘New Path’ to start creating new content deployment job and fill the from as below


3. Click ‘OK’ will create a path (“Export WTU”) as well as Quick Deploy job as follows (A Quick Deploy feature supports the deployment of a single page by authors)


4. Then use “New Job” option or “Create Job” from the context menu as below to create a job.


While creating the job, if we select the database snapshots option, a snapshot of the source content database will be created and it will be used to perform the export, instead of directly using live content database. This option prevents any issues that can be occurred if users edit the content while the job is running. Snapshot will be automatically deleted after the job run.

There is an option to test the job before its actual run.


However, test completed does not mean that the job will run without any errors. It might still fail in the middle. In that case click on the failed status (hyperlink) will present a log of all errors and warnings and reason for the failure can be identified.

If the testing is successful we can run the job immediately with ‘Run Now’ option or we can schedule it.

** In destination server content deployment settings, if we select ‘Require encryption’ option



And specify an http URL in source configuration, we will get following error.


So we have to either configure https in destination and specify https central admin URL or use ‘Do not require encryption’ option.


** If the content deployment failed for the first time and if we run it for the second time, we will probably see following error;
The exception thrown was 'Microsoft.SharePoint.SPException' : 'Unable to import the folder _catalogs/masterpage/Forms/Page Layout. There is already an object with the Id aae2e….cbb43dfab73f in the database from another site collection.'”

In order to fix this error I had to detach and reattach content databases from other web applications and delete and create destination web application.

Friday, December 21, 2012

Output Caching to Speed up SharePoint 2010 Publishing Sites

Caching frequently accessed pages can results faster response time for any web site. Output caching in SharePoint 2010 behaves similarly to output caching in ASP.NET. With SharePoint 2010 output caching, subsequent requests for a same page within the cache duration will be served from the output page without executing the code that created it. That means no round trip to the database to fetch the source code for the page or controls on the page, resulting less CPU time to serve the page.

In order to enable Output Caching for a site collection;
From the root site ‘Site Settings’, find ‘Site collection output cache’ from the Site Collection Administration section.


Select the Enable output cache check box to enable output caching. We can select different cache profiles for anonymous users and authenticated users. In the below figure I have chosen a cache profile from the Anonymous Cache Profile list. This profile is applied when anonymous users access a site in this site collection. For authenticated users output caching is disabled. Also there are options to check if publishing sites or page layouts need to use different output cache profiles.


By selecting 'Enable debug cache information on pages' option, we can see additional cache information on the page source. (Right click -> View page source)

Display cache profile and the date and time that page contents were last rendered;


Display reason why output cache is not used;


Available site collection cache profiles can be accessed by navigating to 'Site collection cache profiles' under Site Settings -> Site Collection Administration section.

Output Caching can be configured at sub-site level also. For that go to;
Site Actions -> Site Settings
Select ‘Site output cache’ in the Site Administration section

More information on output caching and creating new cache profiles can be found at in MSDN here.

Without enabling output caching, initial load took 3.41 seconds.


Without enabling output caching, re-loading of the same page took 3.01 seconds.


After enabling output caching, re-loading of the same page took 33 milliseconds only.

Monday, December 17, 2012

Search Scope Rules - Property Values for “contentclass” Property

In my previous post on PowerShell Script to Create Search Scopes, I used “contentclass” property to create rules by selecting Property Query for scope rule type.

$rule = New-SPEnterpriseSearchQueryScopeRule -RuleType PropertyQuery -ManagedProperty "contentclass" -PropertyValue "STS_List" -FilterBehavior "Exclude" -url $webAppUrl -scope $createdScope -SearchApplication $SSA

Here is a list of various values for contentclass that can be used as property values:

Site:                                 STS_Web
Site Collection:                   STS_Site
Pages Library:                    STS_List_850
Page:                                STS_ListItem_850
Document Library:               STS_List_DocumentLibrary
Document Library Items:      STS_ListItem_DocumentLibrary
Custom List:                      STS_List
Custom List Item:               STS_ListItem
Links List:                          STS_List_Links
Links List Item:                   STS_ListItem_Links
Tasks List:                         STS_List_Tasks
Tasks List Item:                  STS_ListItem_Tasks
Events List:                       STS_List_Events
Events List Item:                STS_ListItem_Events
Announcements List:           STS_List_Announcements
Announcements List Item:    STS_ListItem_Announcements
Contacts List:                     STS_List_Contacts
Contacts List Item:              STS_ListItem_Contacts
Discussion List:                   STS_List_DiscussionBoard
Discussion List Item:            STS_ListItem_DiscussionBoard
Issue Tracking List:             STS_List_IssueTracking
Issue Tracking List Item:      STS_ListItem_IssueTracking
Project Tasks List:              STS_List_GanttTasks
Project Tasks List Item:       STS_ListItem_GanttTasks
Survey List:                       STS_List_Survey
Survey List Item:                STS_ListItem_Survey
Picture Library:                   STS_List_PictureLibrary
Picture Library Item:            STS_ListItem_PictureLibrary
Web Page Library:               STS_List_WebPageLibrary
Web Page Library Item:        STS_ListItem_WebPageLibrary
Form Library:                      STS_List_XMLForm
Form Library Item:               STS_ListItem_XMLForm
Search Query:                    urn:content-class:SPSSearchQuery
News Listing:                     urn:content-class:SPSListing:News
People:                             urn:content-class:SPSPeople
Category:                          urn:content-classes:SPSCategory
Listing:                             urn:content-classes:SPSListing
Person Listing:                   urn:content-classes:SPSPersonListing
Text Listing:                      urn:content-classes:SPSTextListing
Site Listing:                       urn:content-classes:SPSSiteListing
Site Registry Listing:           urn:content-classes:SPSSiteRegistry

Thursday, December 13, 2012

PowerShell Script to Create Search Scopes - SharePoint 2010

Manually creating search scopes is time consuming when the number of scopes and rules are large. PowerShell comes handy in this situation and following is an example script which creates search scopes based on an xml file.

Scenario: I have a root site collection and within that there are sub-sites for four states. Search scopes need to be created in a way that searching from a state should not return data from any other state but from the current state and any sub-site in the root level and current state site. Also data from custom lists need to be skipped.

Site Structure







StateSites.xml
<StateSites>
  <State name="Alberta" url="/alberta" />   
  <State name="Manitoba" url="/manitoba" />           
  <State name="Massachusetts" url="/massachusetts" />        
  <State name="Ontario" url="/ontario" />                    
</StateSites>

Following PowerShell script takes Search Service Application name and web application URL as inputs, read the ‘StateSites.xml’ and creates search scopes for each state mentioned in the XML file, in this case four scopes called ‘Alberta’, ‘Manitoba’, ‘Massachusetts’, and ‘Ontario’. Each scope contains rules to check the root URL and then exclude other states and list data.


#----------------------------------------------------
[string]$AdminServiceName = "SPAdminV4"
[string]$webAppUrl = "http://derdev02:40920"
[string]$SSAName = "Search Service Application"
[string]$scopeXML = "C:\SearchScopes\StateSites.xml"

function read-XML()
{
 try
 {
  Write-Host -f green "Creating Scopes...`n"
  if([string]::IsNullOrEmpty($scopeXML))
  {
   return
  }

  [xml]$scopeFile = Get-Content $scopeXML
  if($scopeFile -eq $null)
  {  
   return
  }
 
  $statesList = $scopeFile.StateSites.State
  foreach ($statenode in $statesList)
  {
   if($statenode -ne $null)
   {
    [string]$stateName = $statenode.Name
    [string]$stateUrl = $statenode.url
 
    write-host "Creating scope `'$stateName`'"
    CreateNew-ScopeState $stateName
   }
  } 
 }
 catch
 {
  Write-Host -red "Exception found"
  write-Host $_.exception.Message
 }
}

function CreateNew-ScopeState([string]$scopeName)
{  
 try
 {
  $SSA=Get-SPEnterPriseSearchServiceApplication -Identity $SSAName
  $newScopeDescription = "State - $scopeName"
  $scope=Get-SPEnterpriseSearchQueryScope -Identity $scopeName -SearchApplication $SSA -ea "silentlycontinue"
  $createdScope = $null

  if($scope -eq $null)
  {
   $createdScope = New-SPEnterpriseSearchQueryScope -Name $scopeName -Description $newScopeDescription -SearchApplication $SSA -DisplayInAdminUI $true
  }
  else
  {
   write-host -f yellow "`'$scopeName`' Scope already exists, now deleting and creating"
   Remove-SPEnterpriseSearchQueryScope -Identity $scopeName -SearchApplication $SSA -confirm:$false
   $createdScope = New-SPEnterpriseSearchQueryScope -Name $scopeName -Description  $newScopeDescription -SearchApplication $SSA -DisplayInAdminUI $true
  }
  $rule = New-SPEnterpriseSearchQueryScopeRule -RuleType "Url" -Url $webAppUrl -MatchingString "$webAppUrl/" -FilterBehavior "Require" -UrlScopeRuleType "Folder" -scope $createdScope
 
  [xml]$scopeFile = Get-Content $scopeXML
  if($scopeFile -eq $null)
  {  
   return
  }
  $statesList = $scopeFile.StateSites.State
  foreach ($statenode in $statesList)
  {
   if($statenode -ne $null)
   {
    [string]$stateName = $statenode.Name
    [string]$stateUrl = $statenode.url
    if($stateName -ne $scopeName)
    {
     [string]$matchString = "$webAppUrl" + "$stateUrl"
     $rule = New-SPEnterpriseSearchQueryScopeRule -RuleType "Url" -Url $webAppUrl -MatchingString $matchString -FilterBehavior "Exclude" -UrlScopeRuleType "Folder" -scope $createdScope                                     
    }
   }
  }
  $rule = New-SPEnterpriseSearchQueryScopeRule -RuleType PropertyQuery -ManagedProperty "contentclass" -PropertyValue "STS_List" -FilterBehavior "Exclude" -url $webAppUrl -scope $createdScope -SearchApplication $SSA
 }
 catch [System.Exception]
 {
  Write-Host -red "Exception found"
  write-Host $_.
 }
}

#Load sharepoint snapins and start admin services if its stoped.
function Setup-PowerShellEnviornment()
{
 #Ensure Microsoft.SharePoint.PowerShell is loaded
 $snapin="Microsoft.SharePoint.PowerShell"

 if (get-pssnapin $snapin -ea "silentlycontinue") {
  write-host -f Green "PSsnapin $snapin is loaded"
 }
 elseif (get-pssnapin $snapin -registered -ea "silentlycontinue") {
  write-host -f Green "PSsnapin $snapin is registered"
  Add-PSSnapin $snapin
  write-host -f Green "PSsnapin $snapin is loaded"
 }
 else {
  write-host -f orange "PSSnapin $snapin not found" -foregroundcolor Red
 }

 #if SPAdminV4 service is not started - start it
 if( $(Get-Service $AdminServiceName).Status -eq "Stopped") {
  #$IsAdminServiceWasRunning = $false
  Start-Service $AdminServiceName
 }
}

Setup-PowerShellEnviornment
read-XML
#----------------------------------------------------

How to test: Create 2 files (.xml and .ps1) and run .ps1 file in a SharePoint environment using Windows PowerShell or SharePoint 2010 Management Shell as an administrator. Make sure to update the 3 parameter at the top of the script.