Wednesday, January 27, 2016

Migrating Site Columns, Site Content Types, Publishing Site Content Types and Meta Data from One SharePoint Environment to another

While migrating SharePoint Sites we also need to migrate Site Columns, Site Content Types from source server to destination server, publish Site Content Types.
Also, we are required to migrate and auto tag the Meta data with contents migrated from one server to another server.
In order to achieve these objectives, follow below steps.

1.       Run below script to migrate Site Columns from source server i-e from where you are migrating. Always Site Columns are required to be migrated first prior to migrating Site Content Types.

$sourceWeb = Get-SPWeb “http://sharepoint/sites/CTH
$xmlFilePath = "C:\Install\Script-SiteColumns.xml"
#Create Export Files
New-Item $xmlFilePath -type file -force
#Export Site Columns to XML file
Add-Content $xmlFilePath "<?xml version=`"1.0`" encoding=`"utf-8`"?>"
Add-Content $xmlFilePath "`n<Fields>"
$sourceWeb.Fields | ForEach-Object {
    if ($_.Group -eq "Custom Columns") {
        Add-Content $xmlFilePath $_.SchemaXml
    }
}
Add-Content $xmlFilePath "</Fields>"
$sourceWeb.Dispose()

Note: Please note that script need to be run against all Groups by replacing “custom column” with respective group name in the script.


2.        This script will generate an xml file which need to be copied on destination SharePoint Farm’s SQL   Server Box and run below script to import all site columns created on Content Type Hub Site.

$destWeb = Get-SPWeb “http://sharepoint/sites/CTH
$installPath = "\\NetworkPathofSQLServer"  -- Network path of SQL Server where file is copied
#Get exported XML file
$fieldsXML = [xml](Get-Content($installPath + "\Script-SiteColumns.xml"))
$fieldsXML.Fields.Field | ForEach-Object {
   
    #Configure core properties belonging to all column types
    $fieldXML = '<Field Type="' + $_.Type + '"
    Name="' + $_.Name + '"
    ID="' + $_.ID + '"
    Description="' + $_.Description + '"
    DisplayName="' + $_.DisplayName + '"
    StaticName="' + $_.StaticName + '"
    Group="' + $_.Group + '"
    Hidden="' + $_.Hidden + '"
    Required="' + $_.Required + '"
    Sealed="' + $_.Sealed + '"'
   
#Configure optional properties belonging to specific column types – you may need to add some extra properties here if present in your XML file
    if ($_.ShowInDisplayForm) { $fieldXML = $fieldXML + "`n" + 'ShowInDisplayForm="' + $_.ShowInDisplayForm + '"'}
    if ($_.ShowInEditForm) { $fieldXML = $fieldXML + "`n" + 'ShowInEditForm="' + $_.ShowInEditForm + '"'}
    if ($_.ShowInListSettings) { $fieldXML = $fieldXML + "`n" + 'ShowInListSettings="' + $_.ShowInListSettings + '"'}
    if ($_.ShowInNewForm) { $fieldXML = $fieldXML + "`n" + 'ShowInNewForm="' + $_.ShowInNewForm + '"'}
       
    if ($_.EnforceUniqueValues) { $fieldXML = $fieldXML + "`n" + 'EnforceUniqueValues="' + $_.EnforceUniqueValues + '"'}
    if ($_.Indexed) { $fieldXML = $fieldXML + "`n" + 'Indexed="' + $_.Indexed + '"'}
    if ($_.Format) { $fieldXML = $fieldXML + "`n" + 'Format="' + $_.Format + '"'}
    if ($_.MaxLength) { $fieldXML = $fieldXML + "`n" + 'MaxLength="' + $_.MaxLength + '"' }
    if ($_.FillInChoice) { $fieldXML = $fieldXML + "`n" + 'FillInChoice="' + $_.FillInChoice + '"' }
    if ($_.NumLines) { $fieldXML = $fieldXML + "`n" + 'NumLines="' + $_.NumLines + '"' }
    if ($_.RichText) { $fieldXML = $fieldXML + "`n" + 'RichText="' + $_.RichText + '"' }
    if ($_.RichTextMode) { $fieldXML = $fieldXML + "`n" + 'RichTextMode="' + $_.RichTextMode + '"' }
    if ($_.IsolateStyles) { $fieldXML = $fieldXML + "`n" + 'IsolateStyles="' + $_.IsolateStyles + '"' }
    if ($_.AppendOnly) { $fieldXML = $fieldXML + "`n" + 'AppendOnly="' + $_.AppendOnly + '"' }
    if ($_.Sortable) { $fieldXML = $fieldXML + "`n" + 'Sortable="' + $_.Sortable + '"' }
    if ($_.RestrictedMode) { $fieldXML = $fieldXML + "`n" + 'RestrictedMode="' + $_.RestrictedMode + '"' }
    if ($_.UnlimitedLengthInDocumentLibrary) { $fieldXML = $fieldXML + "`n" + 'UnlimitedLengthInDocumentLibrary="' + $_.UnlimitedLengthInDocumentLibrary + '"' }
    if ($_.CanToggleHidden) { $fieldXML = $fieldXML + "`n" + 'CanToggleHidden="' + $_.CanToggleHidden + '"' }
    if ($_.List) { $fieldXML = $fieldXML + "`n" + 'List="' + $_.List + '"' }
    if ($_.ShowField) { $fieldXML = $fieldXML + "`n" + 'ShowField="' + $_.ShowField + '"' }
    if ($_.UserSelectionMode) { $fieldXML = $fieldXML + "`n" + 'UserSelectionMode="' + $_.UserSelectionMode + '"' }
    if ($_.UserSelectionScope) { $fieldXML = $fieldXML + "`n" + 'UserSelectionScope="' + $_.UserSelectionScope + '"' }
    if ($_.BaseType) { $fieldXML = $fieldXML + "`n" + 'BaseType="' + $_.BaseType + '"' }
    if ($_.Mult) { $fieldXML = $fieldXML + "`n" + 'Mult="' + $_.Mult + '"' }
    if ($_.ReadOnly) { $fieldXML = $fieldXML + "`n" + 'ReadOnly="' + $_.ReadOnly + '"' }
    if ($_.FieldRef) { $fieldXML = $fieldXML + "`n" + 'FieldRef="' + $_.FieldRef + '"' }  
    $fieldXML = $fieldXML + ">"
    #Create choices if choice column
    if ($_.Type -eq "Choice") {
        $fieldXML = $fieldXML + "`n<CHOICES>"
        $_.Choices.Choice | ForEach-Object {
           $fieldXML = $fieldXML + "`n<CHOICE>" + $_ + "</CHOICE>"
        }
        $fieldXML = $fieldXML + "`n</CHOICES>"
    }
   
    #Set Default value, if specified 
    if ($_.Default) { $fieldXML = $fieldXML + "`n<Default>" + $_.Default + "</Default>" }
        #End XML tag specified for this field
    $fieldXML = $fieldXML + "</Field>"
        #Create column on the site
    $destWeb.Fields.AddFieldAsXml($fieldXML.Replace("&","&amp;"))
    write-host "Created site column" $_.DisplayName "on" $destWeb.Url
        $destWeb.Dispose()
}
Note: Replace the SPWeb url with destination server url and provide path where the export file has been saved on SQL Server box.


3.       Now, after successful export and import of Site Columns, run below script on source server to export all Content Types. This will generate an XML file on provided path.

$sourceWeb = Get-SPWeb “http://sharepoint/sites/CTH
$xmlFilePath = "C:\Install\Script-SiteContentTypes.xml"
#Create Export File
New-Item $xmlFilePath -type file -force
#Export Content Types to XML file
Add-Content $xmlFilePath "<?xml version=`"1.0`" encoding=`"utf-8`"?>"
Add-Content $xmlFilePath "`n<ContentTypes>"
$sourceWeb.ContentTypes | ForEach-Object {
    if ($_.Group -eq "PPL Projects General") {
        Add-Content $xmlFilePath $_.SchemaXml
    }
}
Add-Content $xmlFilePath "</ContentTypes>"
$sourceWeb.Dispose()


4.       Once Export Site Content Type script executes successfully, copy the generated XML file to SQL Server on Destination SharePoint Farm.
5.       Run below script by providing site url and file path.

$destWeb = Get-SPWeb “http:// sharepoint /sites/CTH
$xmlFilePath = "C:\Install\Script-SiteContentTypes.xml"
#Create Site Content Types
$ctsXML = [xml](Get-Content($xmlFilePath))
$ctsXML.ContentTypes.ContentType | ForEach-Object {
    #Create Content Type object inheriting from parent
    $spContentType = New-Object Microsoft.SharePoint.SPContentType   ($_.ID,$destWeb.ContentTypes,$_.Name)
        #Set Content Type description and group
    $spContentType.Description = $_.Description
    $spContentType.Group = $_.Group
   
    $_.Fields.Field  | ForEach-Object {
        if(!$spContentType.FieldLinks[$_.DisplayName])
        {
            #Create a field link for the Content Type by getting an existing column
            $spFieldLink = New-Object Microsoft.SharePoint.SPFieldLink ($destWeb.Fields[$_.DisplayName])
                    #Check to see if column should be Optional, Required or Hidden
            if ($_.Required -eq "TRUE") {$spFieldLink.Required = $true}
            if ($_.Hidden -eq "TRUE") {$spFieldLink.Hidden = $true}
                    #Add column to Content Type
            $spContentType.FieldLinks.Add($spFieldLink)
        }
    }
   
    #Create Content Type on the site and update Content Type object
    $ct = $destWeb.ContentTypes.Add($spContentType)
    $spContentType.Update()
    write-host "Content type" $ct.Name "has been created"
}
$destWeb.Dispose()


6.       Once Site Columns and Site Content Types have been imported successfully, run below script to     publish content types on Sites which inherit Content Types from Content Type Hub Site.

Note: You need to execute script against all Site Content Type Groups by providing group name in $group variable.

Param(
 [string] $siteUrl="http://sharepoint /sites/CTHSite/",
 [string] $group ="GroupNameofContentType "
)
if(!($siteUrl))
{
 Write-Host "Error: Site parameter missing." -ForegroundColor Red
 Write-Host "Usage: Update-ContentTypeHub $siteUrl $group"
 return
}
if(!($group))
{
 Write-Host "Error: Group parameter missing." -ForegroundColor Red
 Write-Host "Usage: Update-ContentTypeHub $siteUrl $group"
 return
}
#Update Content Type hub subscribers for all web apps

#Set the execution policy
Set-ExecutionPolicy Unrestricted
#Add the required SP snapins
Add-PSSnapIn Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
function Publish-ContentTypeHub {
 param
 (
 [parameter(mandatory=$true)][string]$CTHUrl,
 [parameter(mandatory=$true)][string]$Group
 )

 $site = Get-SPSite $CTHUrl
 if(!($site -eq $null))
 {
 $contentTypePublisher = New-Object Microsoft.SharePoint.Taxonomy.ContentTypeSync.ContentTypePublisher ($site)
 $site.RootWeb.ContentTypes | ? {$_.Group -match $Group} | % {
 $contentTypePublisher.Publish($_)
 write-host "Content type" $_.Name "has been republished" -foregroundcolor Green
 }
 }
}

#Updates the Content Type subscribers for each web application
function Update-ContentHub([string]$url)
{
 #Get the Timer job info
 $job = Get-SPTimerJob -WebApplication $url | ?{ $_.Name -like "MetadataSubscriberTimerJob"}

 #check that the job is not null
 if ($job -ne $null)
 {
 #run the timer job
 $job | Start-SPTimerJob

 #run the admin action
 Start-SPAdminJob -ErrorAction SilentlyContinue

 }

}
#force publish of the content types
Publish-ContentTypeHub $siteUrl $group
 write-host
 write-host "Waiting for 10 seconds for job to finish..."
Start-Sleep -s 10
 write-host
#get the web applications and update the content type hub subscribers for each web application
Get-SPWebApplication | ForEach-Object { Write-Host "Updating Metadata for site:" $_.Url; Update-ContentHub -url $_.Url }

7.       After successful migration of Site Columns and Content Types, we need to migrate Meta data from Source to Destination Server. In order to migrate Metadata run below script in Power Shell.

$mmsAppId= "b177f3f1-a492-410b-a745-8a3692e09dfe"
$mmsproxy = Get-SPServiceApplicationProxy -Identity "94b675b1-9a68-40b3-8f34-654a3247c592"
Export-SPMetadataWebServicePartitionData -Identity $mmsAppId -ServiceProxy $mmsproxy -Path "c:\exportfile"

Note: Run below scripts to find out Managed Meta Data AppId and Managed Meta Data Proxy Id.
metadataApp= Get-SpServiceApplication | ? {$_.TypeName -eq "Managed Metadata Service"}
$mmsAppId = $metadataApp.Id

$mmsproxy = Get-SPServiceApplicationProxy | ?{$_.TypeName -eq "Managed Metadata Service Connection"}



8.       Copy the “exportfile” generated after successful execution of above script and paste on destination SQL server drive and run below script to import Meta Data Term Store.

$mmsAppId= "b177f3f1-a492-410b-a745-8a3692e09dfe"
$mmsproxy = Get-SPServiceApplicationProxy -Identity "b851e5f2-c96b-44e2-8dd9-5b885009969e"
Import-SPMetadataWebServicePartitionData -Identity $mmsAppId -ServiceProxy $mmsproxy -Path "C:\ExportFile\exportfile.bak" -OverwriteExisting;

Note: Execute below scripts to find out $mmAppId and $mmsproxy parameters on destination server. In –Path please provide network path of SQL Server where exportfile has been saved.
metadataApp= Get-SpServiceApplication | ? {$_.TypeName -eq "Managed Metadata Service"}
$mmsAppId = $metadataApp.Id

$mmsproxy = Get-SPServiceApplicationProxy | ?{$_.TypeName -eq "Managed Metadata Service Connection"}





Friday, October 16, 2015

Enabling “Sign in as a different user” option in SharePoint 2013

By default SharePoint 2013 doesn’t provide option for sign in as a different user unlike we had option in SharePoint 2010 ribbon.





Microsoft has removed this option in SharePoint 2013 because of Caching problems, Documents opened in external applications are saved with an unexpected user account and many more.
In order to enable this option we need to follow below steps:
Step 1: Go to 
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATES\CONTROLTEMPLEATS.

Here we have a file named welcome.ascx.





Step: 2
Open welcome.ascx in Visual Studio or in Notepad and add the following code and save:
<SharePoint:MenuItemTemplate runat="server" ID="ID_LoginAsDifferentUser"
  Text="<%$Resources:wss,personalactions_loginasdifferentuser%>"
  Description="<%$Resources:wss,personalactions_loginasdifferentuserdescription%>"
  MenuGroupId="100"
  Sequence="100"
  UseShortId="true"
  />




And it should be above the tag which has ID_RequestAcess.
Step: 3
Refresh the site, and it's been enabled: