Author Archives: Senthamil

About Senthamil

I am a Microsoft MVP in Office Development

Resolve people picker control using jQuery

Please follow my prerequisite blog to add the jQuery dependency on the master page. The below jQuery code will work with jQuery dependency.

peoplemanager

In this blog I will discuss how to use jQuery to auto complete the people field with the input person manager property. To do it please follow below steps

Step 1:

Navigate to my Github URL to download the below files from the repository

  • getManager.js
  • getManagerHtml.txt
  • Leave App.stp

Step 2:

Upload the Leave App.stp to the List template Gallery. Then Create a list using the template uploaded. In my case I Created a list with name Leave Application.

Step 3:

Upload the files getmanager.js & getManagerHtml.txt to the Site Assets library under the site content. Usually I will create a folder scripts under Site Assets library to upload the files. So the sample below will use the siteassets/scripts/<file name>. If you uploading the file to different library make sure you change the path in the getManagerHtml.txt file.

Step 4:

Navigate to the List “Leave Application” you have created in Step 1: In my case it is under URL https://<sitecollection>/ms/Lists/Leave%20Application/AllItems.aspx , /ms is the subsite name I am using. In your case it may be different based on site name. Click on New Item to open the New Item form.

Locate the top settings icon and click on it to open Edit Page. This will allow to add webpart to the edit form. Add the content editor webpart. In the content editor webpart edit it to add the getManagerHtml.txt file path to it. After adding the Path save the Page.

Step 5:

So now the script will add the Get Manager button at run time next to the Input field. But before that you should set the correct ID of the control in the getManagerHtml.txt. Now go to the Site Assets library and then to the getManager.js file. Open the getManager.js in the favourite editor you have. You can open even in notepad. In my case I use the Visual Studio code to open the file. You can Map the folder to the Network drive to open it easier in VS code. The ID marked below in the picture has to be replaced by your ID.

To find out the ID use the developer tool in the browser to identify. I use Edge and F12 key to open the developer tool. Once you identify the ID replace it in the js file and save the file.

Once the changes are saved in the getmanager.js file, go back to the Leave Application New Item page and refresh. Now you should be able to see Get Manager button. Type the Name in the Applying People. Then click on the Get Manager button to auto fill the Manager on the Manager People Picker. The code will auto fill and then will make the control disable.

The Java Script code actually uses the People Manager api to get the Applying People control details. Get the Account name and call to the people manager API to get the manager. Once the Manager field is retrieved from CSOM it sets it to the People picker and automatically resolve the name in the control. You can modify the code to get other details if you wanted to.

Hope this works!!!

Get Taxonomy Term set, custom properties & Terms using JSOM

Please follow my prerequisite blog to add the jQuery dependency on the master page. The below jQuery code will work with jQuery dependency.

In this blog the jQuery code will get the terms from a specific termset. Each term will have a local property cssclass & cssfname. The JSOM code will get the custom property and create a bootstrap button navigation. Term ID will be a Query string for navigation.

The Navigation termset on the screenshot is created dynamically based on the Taxonomy. The color of button asp.net, azure, crm, sharepoint are colored based on the CSSCLASS property from the term.

 

Step 1: Download the files

Navigate to my Github to download the files. The Github has the termsetHtml.txt & termsetScript.js

Step 2: Upload To SiteAssets

Upload both the files to SiteAssets-> Scripts folder. Create Scripts folder inside the Site Assets to upload. If you are not using scripts folder make sure you change the path in termsetHtml.txt

Step 3: Add to SharePoint

Now add the Content Editor webpart to the Page. Edit the content editor webpart and add the full path of the termsetHtml.txt file. Save the webpart and page. If the reference to jquery, js and code are correct the termset will be loaded and color based on css name

jQuery based client side site review with smileys

 

feedbackvideo

Before proceeding please read the prerequisite blog posted by me. Need to setup the referenced js and css files in the master page. If you don’t want to add in master page. Please add those in the txt file which is added below.

Navigate to Github to get the files required for this Review / Feedback jQuery

The Github have following files

  1. Feedback.stp – List template used to submit review details
  2. Feedbackhtml.txt – This file contains the html and the style
  3. feedbackMaster.js – this is the javascript to submit the Feedbacks list
  4. gif file no need to use…

Step 1: List Template

Upload the list template to the site and create the Feedbacks list. The js code will get the list instance by the title Feedbacks so use the name Feedbacks while creating the List

Step 2: Upload the Files

In my case the site url is https://<sitecollection>/ms/ so navigate the site assets under your site where you want the review component. Under Site Assets create a folder called scripts. Under the scripts folder upload both the js and the txt file, that is feedbackhtml.txt and feedbackmaster.js. If you don’t want to upload to siteassets ->scripts folder make sure you change the path of the js file. The js file path must be the folder you are using.

Step 3: WebPart Add

After the files are uploaded to the scripts folder. Go to the page where you want the review jquery app. Edit the pager and add the content editor webpart to the page. Edit the webpart and in the path text enter the full path to the txt file. https://<sitecollection>/ms/siteassets/scripts/feedbackhtml.txt . Now save the webpart and the page. If dependency js, css are correct and the path to feedbackMaster.js is correct the feedback / review will be displayed as per the gif picture above.

The javascript uses the site url for the variable. Make sure you point to your site path. In my case the site url is /ms

Setup prerequisite – msisgreat masterpage & js dependencies

In this blog I will go through how to setup my java script libraries to the Master Page. All my java script sample in the blog will refer to the customized master page. This customized master page for me I named it as msisgreat.master.

Creating master page

If you want to customize the master page in SharePoint first you need to enable the Publishing Infrastructure & Publishing Feature. Once enabled open the https://<sitecollection>/_catalogs/masterpage in the windows explorer view. I like the Oslo.master page because it does not have the left navigation control. So in all my sample code I use the oslo.master as the base master page. To create the custom master page with oslo.master as base. Just select the below files in the explorer view

Oslo.master

Oslo.html

Oslo.preview

Copy all the above files and paste again in the same masterpage folder. Now you will see oslo copy.master, oslo copy.html & oslo copy.preview. Now just rename only .html and .preview file to the name you wanted. In my case I renamed oslo copy.html to msisgreat.html & renamed oslo copy.preview to msisgreat.preview. Please do not rename the .master file because this file is always tied to.html, renaming .html will rename .master file or new file will be created with msisgreat.master.

Now that you have 3 files with msisgreat name publish all 3 files to a major version. First time you need to publish as major version so that you can apply as a master page in the site settings page.

Copying the dependency files

Navigate to my github webpage for js project in this URL Use the clone download Zip option to get all the files to the local directory. Once zip file is downloaded unzip it to any temp folder. In the unzipped folder look for dependency folder.

Open the masterpage (https://<sitecollection>/_catalogs/masterpage) in the explorer view. Now create a folder called custommaster inside the masterpage folder. Navigate inside the custommaster folder and paste the files copied in early step into this folder. This will take longer depends on the speed of the network. For me it took 25 minutes to copy all the dependency files. Once coped the folder structure will look like below

 

Adding the dependency snippet

Once the master page is created and ready. Open the masterpage folder in windows explorer view. Locate the msisgreat.html file, use your popular editor in my case Visual Studio code to open the html file. Once the file is opened in the editor locate for the below tag

<![CDATA[ [endif] ]]> <!–[if lte IE 8]>

<style type=”text/css”>//<![CDATA[

.ms-core-animation-transparent,

.ms-core-animation-transparent img

{

-ms-filter:”alpha(opacity=0)”;

}

.ms-isBot .ms-core-animation-transparent,

.ms-isBot .ms-core-animation-transparent img

{

-ms-filter:””;

}

//]]></style>

<![endif]–>

 

Locate the above snippet of the code in the master page. Once you locate. Now copy the below code and paste it after that <![endif]à

<link rel=”stylesheet” href=”./custommaster/animate/animate.css” />

<link rel=”stylesheet” href=”./custommaster/jq/jquery-ui-1.12.1/jquery-ui.css” />

<link rel=”stylesheet” href=”./custommaster/style/mystyles.css” />

<link rel=”stylesheet” href=”./custommaster/fa5.3.1/css/all.min.css” />

http://./custommaster/jQ/jquery-3.3.1.min.js

http://./custommaster/jq/jquery-ui-1.12.1/jquery-ui.js

<link rel=”stylesheet” type=”text/css” href=”./custommaster/tooltipster/css/tooltipster.bundle.min.css” />

<link rel=”stylesheet” type=”text/css” href=”./custommaster/tooltipster/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-shadow.min.css” />

<link rel=”stylesheet” type=”text/css” href=”./custommaster/tooltipster/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-punk.min.css” />

http://./custommaster/tooltipster/js/tooltipster.bundle.min.js

<link rel=”stylesheet” type=”text/css” href=”./custommaster/bootstrap4.1.3/css/bootstrap.min.css” />

http://./custommaster/bootstrap4.1.3/js/bootstrap.min.js

 

Basically the above snippet will add all the dependencies you wanted to the master page. Now save the master page and publish only .html file. Do not touch the .master file in any scenario. The bootstrap references are optional. Beware this will completely change your site font and color. So add only if you need bootstrap to beautify pages.

 

Surface Go Unboxing & My Personal Review

This blogpost is my 100th blog. Celebrating my 100th blog with my new Surface Go (4 GB model). Actually this blog was written using Surface Go.

Release Date in Singapore 28th Aug 2018
Shipped Date 31 Aug 2018
Price SGD (including type cover) S$ 725.10 (this is 10% student price)

Unboxing the Surface Go

Below are the items included in the Box

  1. Surface Go device
  2. Power Supply
  3. Starter Guide
  4. Warranty details

Surface Go devices are mainly targeted for Students to make it easy to carry, light weight and productive during the classes. The Windows 10 configuration has optimized settings specific to education sector. There is a very good article around it here

The Surface Go has below ports

  1. 1 x USB-C
  2. 3.5 mm headphone jack
  3. 1 x Surface Connect port
  4. Surface Type Cover port
  5. microSDXC card reader

Full Tech Spec – My Surface Go

Software Windows 10 Home (Out of S mode)

Microsoft Office 365 Home – My Live subscription

Dimensions 9.65″ x 6.90″ x 0.33″ (245 mm x 175 mm x 8.30 mm)
Weight Starting at 1.15 lbs (522 g), not including Type Cover
Storage eMMC drive: 64GB
Display Screen: 10″ PixelSense™ Display

Resolution: 1800 x 1200 (217 PPI) resolution

Aspect ratio: 3:2

Contrast ratio: 1500:1

Touch: 10-point multi-touch

Corning® Gorilla® Glass 3

Battery life Up to 9 hours of battery life – I am yet to test that
Processor Intel® Pentium® Gold Processor 4415Y
Security TPM 2.0 for enterprise security

Enterprise-grade protection with Windows Hello face sign-in

Memory 4GB
Wireless Wi-Fi: IEEE 802.11 a/b/g/n/ac compatible

Bluetooth Wireless 4.1 technology

Connections 1 x USB-C

3.5 mm headphone jack

1 x Surface Connect port

Surface Type Cover port

microSDXC card reader

Cameras, video, and audio Windows Hello face authentication camera (front-facing)

5.0MP front-facing camera with 1080p Skype HD video

8.0MP rear-facing autofocus camera with 1080p HD video

Single microphone

2W stereo speakers with Dolby® Audio™ Premium

Graphics Intel® HD Graphics 615
Exterior Casing: Magnesium

Color: Silver

Physical buttons: Volume, Power

Sensors Ambient light sensor

Accelerometer

Gyroscope

Magnetometer

My Reviews

First Look

The device looks super cute with the slim down in size. You can visualize the sizes between devices in the below picture. The device has smooth curved edges compared to Surface Pro. Compared to other tablets in market this one is slightly thicker.

Pros:

Smaller and Handy (245 mm x 175 mm x 8.30 mm)

Light weight (522 g)

Fit easily to your hand bag and carry

Comes with built in stand, easy to work

Cons:

Slightly thicker than usual tablets.

Backward Compatibility & Features

Once I unbox the Go device I try to plug in to my Surface Dock, you guess what it works like charm. Any USB devices connected to Dock works too. I even tried to charge using the Surface Pro charger and it works. The Type C port is easy to extend multiple monitors. Surface Pen and the Surface Dial also works without any glitch. It has a Micro SD slot at the back hidden behind stand like in Surface Pro.

Pros:

Works with Surface Dock

Works with Surface Pen, Dial and Surface Pro charger.

Micro SD slot available

Type C port for Extension

Cons:

No USB port , you need to buy Type C to USB in case you want to connect any external devices.

CPU Performance

To identify the performance, I used 2 benchmark tools GeekBench 4 and the NovaBench. Both tools have their own benchmark scores for CPU, Memory and GPU. Below is the screenshot of the tool results.

The benchmark score shows Surface Go performs on much better than $500 USD priced Laptop models. It scores better in GPU and graphics.

Using Novabench Tool for getting the benchmark of performance. The Novabench tool will have its own score to come up with the benchmark.

Recursively update File metadata taxonomy field

In this blog you will find a CSOM PowerShell code to update Taxonomy field of a file. The script in the Github will recursively go through all the folders in a library and update the taxonomy field. The script update the field to the specific term you mention. To update the taxonomy field you will need the below details

$termValue.Label

$termValue.TermGuid

$termValue.WssId

To find the WSSID of the term you will need to navigate to the Site collection level Hidden Taxonomy List using the URL /Lists/TaxonomyHiddenList/AllItems.aspx. In the list you can find the term and get the Item ID.

In the above screenshot the wssid for the Presentation term is 2

The complete PowerShell below, you can also find in my github

Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.dll"
Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.Taxonomy.dll"

$global:CopiedCount = 0
$username = ""
$password = ""
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)

$destUrl = ""
$destLibrary = "Documents"
$destinationFolder = "/sites//Shared Documents//"
$termName= "MyTerm"
$termGUID = "TERM GUID HERE"
$termWssId = wssid ## wssid of the term, you can find it from hiddentaxonomy list and the ID of the term in that list /Lists/TaxonomyHiddenList/AllItems.aspx
$libFieldColumnName = "ColumnName"


########
function UpdateFileColumns
{
    param($sourceFileCopy, $fListItem)   
        try{
        $modDate = $fListItem["Modified"]
        $modUser = $fListItem["Editor"]
        
        $termValue = New-Object Microsoft.SharePoint.Client.Taxonomy.TaxonomyFieldValue
        $termValue.Label = $termName #provide the term label here to change
        $termValue.TermGuid = $termGUID # term GUID here
        $termValue.WssId = $termWssId
        $taxField.SetFieldValueByValue($fListItem, $termValue)
        $fListItem["Modified"] = $modDate
        $fListItem["Editor"] = $modUser
        $fListItem.Update()
        $destContext.Load($fListItem)
        $destContext.ExecuteQuery()      
        $global:CopiedCount = $global:CopiedCount +1
        Write-Host "Updated the file. File Count: " $global:CopiedCount -ForegroundColor Cyan       
        }catch{
            $statusRemark = $statusRemark + "Creation error: " + $_.Exception.Message
            Write-Host $statusRemark -ForegroundColor Red
        } 
}

function CreateFolders
{ 
    param (
        [Parameter(Mandatory=$true)] $srcfolder        
        )

    $fileCol = $srcfolder.Files    
    $destContext.Load($fileCol)
    $destContext.ExecuteQuery()
    foreach ($f in $fileCol)
    {                          
        $ListItem = $f.ListItemAllFields                         
        $destContext.Load($f)
        $destContext.Load($ListItem)
        $destContext.ExecuteQuery()
        Write-Host "Updating file : " $f.ServerRelativeUrl                                                 
        UpdateFileColumns $f $ListItem

    } ## end of for each file
    $fL1FolderColl = $srcfolder.Folders
    $destContext.Load($fL1FolderColl);
    $destContext.ExecuteQuery();
    foreach ($myFolder in $fL1FolderColl)
    {
        $destContext.Load($myFolder)
        $destContext.ExecuteQuery()
        CreateFolders $myFolder
    }
} 

$destContext = New-Object Microsoft.SharePoint.Client.ClientContext($destUrl) 
$destContext.Credentials = $credentials
$destContext.RequestTimeout = 1000 * 60 * 10
try
{
    $destWeb = $destContext.Web
    $destList = $destWeb.Lists.GetByTitle($destLibrary)
    $destContext.Load($destWeb)
    $destContext.Load($destList)
    $field = $destList.Fields.GetByInternalNameOrTitle($libFieldColumnName) # column Name here 
    $destContext.Load($field)
    $destContext.ExecuteQuery()
}
catch{
    Write-Host $_.Exception.Message -ForegroundColor Red
    exit
}

$taxField = [Microsoft.SharePoint.Client.ClientContext].GetMethod("CastTo").MakeGenericMethod([Microsoft.SharePoint.Client.Taxonomy.TaxonomyField]).Invoke($destContext, $field)

$folder = $destWeb.GetFolderByServerRelativeUrl($destinationFolder)
$destContext.Load($folder)
$destContext.ExecuteQuery()    
CreateFolders $folder
$destContext.Dispose()
$now=Get-Date -format "dd-MMM-yyyy HH:mm"
Write-Host "Script End : '$($now)'"
##############

Create termset & terms using CSOM PowerShell

CSOM has the rich API to create and manage the Termset and terms within SharePoint. The PowerShell code in the Github uses the sample XML here to create a Termset with hierarchy.

The full PowerShell code below

Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.dll"
Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.Taxonomy.dll"

$now=Get-Date -format "dd-MMM-yy,HH:mm:ss"
Write-Host "Script Start : '$($now)'" -ForegroundColor Yellow

$username = "user name"
$password = ""
$srcUrl = "SITE URL"
$xmlFilePath = "C:\Github\msisgreat\ps\ps\sample\CountriesTerm.xml" # change this to xml path with the termset defined

$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)

function CreateTerm($context, $termSet, $label, $lcid, $termXmlData)
{
  $terms = $termSet.Terms
  $context.Load($terms)
  $context.ExecuteQuery()
  $term = $terms | Where-Object {$_.Name -eq $label}
  if($term)
  {
    Write-Host "Term" $label   "already exists." -foregroundcolor Blue
    $termXmlData.Term | ForEach-Object { CreateTerm $context $term $_.Name $lcid $_ }
  }
  elseif($label)
  {
    Write-Host "Creating term " $label -foregroundcolor yellow
    $term = $termSet.CreateTerm($label, $lcid, [System.Guid]::NewGuid())
    try
    {
      $context.ExecuteQuery()
      Write-Host "Term" $label "Created successfully" -foregroundcolor Green
      $termXmlData.Term | ForEach-Object { CreateTerm $context $term $_.Name $lcid $_ }
    }
    catch
    {
      Write-Host "Error while creating Term" $label $_.Exception.Message -foregroundcolor Red
      return
    }
  }
}

function CreateTermSet($context, $group, $termSetXml, $lcid)
{
  $termSets = $group.TermSets
  $context.Load($termSets)
  $context.ExecuteQuery()
  $termSet = $termSets | Where-Object {$_.Name -eq $termSetXml.Name}  

  if($termSet)
  {
  Write-Host "Termset" $termSetXml.Name   "already exists."   -foregroundcolor Blue
  $termSet = $group.TermSets.GetByName($termSetXml.Name)
  $context.Load($termSet)
  $context.ExecuteQuery()
  }
  else
  {
    Write-Host "Creating term set" $termSetXml.Name -foregroundcolor yellow
    $termSet = $group.CreateTermSet($termSetXml.Name, [System.Guid]::NewGuid(), $lcid)
    try
    {
      $context.ExecuteQuery()
      Write-Host "Term set " $termSetXml.Name "Created successfully" -foregroundcolor Green
    }
    catch
    {
      Write-Host "Error while creating Term set" $termSetXml.Name $_.Exception.Message -foregroundcolor Red
      return
    }
  }
  $termSetXml.Term | ForEach-Object { CreateTerm $context $termSet $_.Name $lcid $_ }
}

function CreateTermSet($context, $group, $termSetXml, $lcid)
{
  $termSets = $group.TermSets
  $context.Load($termSets)
  $context.ExecuteQuery()
  $termSet = $termSets | Where-Object {$_.Name -eq $termSetXml.Name}  

  if($termSet)
  {
  Write-Host "Termset" $termSetXml.Name   "already exists."   -foregroundcolor Cyan
  $termSet = $group.TermSets.GetByName($termSetXml.Name)
  $context.Load($termSet)
  $context.ExecuteQuery()
  }
  else
  {
    Write-Host "Creating term set" $termSetXml.Name -foregroundcolor yellow
    $termSet = $group.CreateTermSet($termSetXml.Name, [System.Guid]::NewGuid(), $lcid)
    try
    {
      $context.ExecuteQuery()
      Write-Host "Term set " $termSetXml.Name "Created successfully" -foregroundcolor Green
    }
    catch
    {
      Write-Host "Error while creating Term set" $termSetXml.Name $_.Exception.Message -foregroundcolor Red
      return
    }
  }
  $termSetXml.Term | ForEach-Object { CreateTerm $context $termSet $_.Name $lcid $_ }
}

function Get-TermStoreInfo
 {
   Write-Host "Loading taxonomy session" -foregroundcolor yellow
   $session = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context)
   $session.UpdateCache();
   $context.Load($session)
   $context.ExecuteQuery()
   Write-Host "Loading term stores" -foregroundcolor yellow
   $termStores = $session.TermStores
   $context.Load($termStores)
   try
   {
     $context.ExecuteQuery()
     $termStore = $termStores[0]
     $context.Load($termStore)
     Write-Host "Term store with the following id is loaded:" $termStore.Id -foregroundcolor Green
   }
   catch
   {
     Write-Host "Error detail while getting term store id" $_.Exception.Message -foregroundcolor Red
     return
   }
   return $termStore
 } 

 function CreateMetadata($context)
{

    Write-Host "Loading the terset xml..." -foregroundcolor Green
    [xml]$xmlContent = (Get-Content $xmlFilePath)
    if (-not $xmlContent)
    {
      Write-Host "Error loading the xml." -foregroundcolor Red
      return
    }
    $termStore = Get-TermStoreInfo $context
    Write-Host "Create Taxonomy group if it is not available" -foregroundcolor yellow
    $sitecollectiontaxonomyGroup = $termStore.GetSiteCollectionGroup($context.Site,$true)
    $context.Load($sitecollectiontaxonomyGroup)
    try
    {
      $context.ExecuteQuery()
      Write-Host "Site collection $url taxonomy group  "$sitecollectiontaxonomyGroup.Name" created or retrived successfully " -foregroundcolor Green
    }
    catch
    {
      Write-Host "Error while creating or getting site collection $url taxonomy group" $_.Exception.Message -foregroundcolor Red
      return
    }

    $xmlContent.TermSets.TermSet |
    ForEach-Object { CreateTermSet $context $sitecollectiontaxonomyGroup $_ $termStore.DefaultLanguage }
} 

### The script starts here to run ####
Write-Host "Authenticating ..." -ForegroundColor White
$context = New-Object Microsoft.SharePoint.Client.ClientContext($srcUrl)
$context.Credentials = $credentials
$web = $context.Web
$site = $context.Site
$context.Load($web)
$context.Load($site)
try {
    $context.ExecuteQuery()
}
catch {
    Write-Host "Error" + $_.Exception.Message -ForegroundColor Red
    exit
}

Write-Host "Connected to the web..." -ForegroundColor Cyan
#Provision Site collection taxonomy group, termset and terms based on SiteCollectionTermsets.xml configuration file
Write-Host "Provisioning Site collection terms started" -foregroundcolor yellow
CreateMetadata ($context)
Write-Host "Provisioning Site collection terms Completed" -foregroundcolor green
$context.dispose()

<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>

Sample XML file for input

Output of the PowerShell

Update Webpart view in a Page programmatically using PowerShell

For a SharePoint Administrator managing the changes in the view for a webpart is a very tiresome job. If a single view changes in the library or list then a page which uses the webpart view has to be manually changed. To change the view in the webpart the administrator has to edit the page, modify webpart and save the page. Imagine if you have 5 pages and each page have 5 webparts and a view is changed. You have to open each page in edit mode and the each webpart edit, change view and save one by one.

To effectively change the webpart view in a page, CSOM have an api to get the webpart in a page as a XML. Manipulate the XML and get the webpart name and view name from xml. Usually when a webpart is added to the page the view xml is cached to the page. So when the view is changed in the library / list the updated view will not be reflected in the page. The PowerShell code will get the webpart and update the view xml

The full code is here you can download

#### To change the webpart view
#### Get the webpart from the page. get the WebPart XmlDef and find the View ID
### List has hidden view for the web part added. So get the view from the List and change that view.
### Its all about that hidden View

Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.dll"
Add-Type -Path ".\CSOM\Microsoft.SharePoint.Client.Runtime.dll"

$now=Get-Date -format "dd-MMM-yy,HH:mm:ss"
$fileFormat = Get-Date -format "dd-MMM-yy_HHmmss"
Write-Host "Script Start : '$($now)'" -ForegroundColor Yellow

$username = ""
$password = ""
$srcUrl = "" # full url like hhtp://my.sharepoint.com/
$sitePath = "/SitePages/"
$srcLibrary = "Documents"
$pagesList = @("Home.aspx") # you can specify many pages to be changed array here
$wepPartChangeList = @{"Documents" = "All Documents" ; } ### dictionary value Key = Web part Title seen on page, Value = View Name from the Library

$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)

Write-Host "Authenticating ..." -ForegroundColor White
$srcContext = New-Object Microsoft.SharePoint.Client.ClientContext($srcUrl)
$srcContext.Credentials = $credentials
$srcWeb = $srcContext.Web
$srcList = $srcWeb.Lists.GetByTitle($srcLibrary)

$srcContext.Load($srcWeb)
$srcContext.Load($srcList)

try{
    $srcContext.ExecuteQuery()
}catch{
    Write-Host $_.Exception.Message -ForegroundColor Red
    exit
}
Write-Host "Connected to the web..." -ForegroundColor Green

foreach($page in $pagesList)
{
    $filePath = $sitePath + $page
    $pageObject = $srcWeb.GetFileByServerRelativeUrl($filePath)
    $srcContext.Load($pageObject)
    $srcContext.ExecuteQuery()
    $WPM = $pageObject.GetLimitedWebPartManager("Shared")

    $webParts = $WPM.WebParts
    $srcContext.Load($WPM)
    $srcContext.Load($webParts)
    $srcContext.ExecuteQuery()

    foreach($wp in $webParts)
    {
        $srcContext.Load($wp.WebPart)
        $srcContext.Load($wp.WebPart.Properties)
        $srcContext.ExecuteQuery()

        if( $wepPartChangeList[$wp.WebPart.Title] -ne $null)
        #if($wp.WebPart.Title.IndexOf("Documents") -gt 0)
        {
            Write-Host "---------- Processing Page  = $($pageObject.Name) Webpart = $($wp.WebPart.Title) ------- " -ForegroundColor Yellow

            $wpXmlContent = $wp.WebPart.Properties["XmlDefinition"]
            $wpXml = New-Object -TypeName XML
            $wpXml.LoadXml($wpXmlContent)
            $viewGUID = $wpXml.View.Name

            $viewName = $null
            $viewName = $wepPartChangeList[$wp.WebPart.Title]
            if($viewName)
            {
                $view = $srcList.Views.GetByTitle($viewName)
                $wpView = $srcList.Views.GetById($viewGUID)
                $srcContext.Load($wpView)
                $srcContext.Load($view)
                $srcContext.ExecuteQuery()
                #$viewXml = New-Object -TypeName XML
                #$viewXml.LoadXml($view.ListViewXml)
                write-host "### WebPart Xml -------Before Xml Change -----" -foreground cyan
                write-host "$($wpView.ListViewXml)"              

                $wpViewFields = $wpView.ViewFields
                $viewFields = $view.ViewFields
                $srcContext.Load($viewFields)
                $srcContext.Load($wpViewFields)
                $srcContext.ExecuteQuery()

                $wpViewFields.RemoveAll()
                foreach($vField in $viewFields)
                {
                    $wpView.ViewFields.Add($vField)
                }

                $wpView.RowLimit = $view.RowLimit
                $wpView.ViewQuery = $view.ViewQuery
                $wpView.Update()
                $srcContext.Load($wpView)
                $srcContext.ExecuteQuery()
                write-host "### WebPart Xml -------After Xml Change -----" -foreground cyan
                write-host "$($wpView.ListViewXml)"
                write-host "*******************************************************************" -foreground cyan
            }
            else
            {
                Write-Host "Unable to fing view for " $wp.WebPart.Title -ForegroundColor Cyan
            }
            #$wp.SaveWebPartChanges()

        }
    }
    #Write-Host "Next Page " 

}
#&gt;

$srcContext.Dispose()
$now=Get-Date -format "dd-MMM-yy,HH:mm:ss"
Write-Host "END : '$($now)'" -ForegroundColor Yellow<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>

webpart

Set SharePoint folder level permission using C# & PowerShell

The PowerShell script here will set the permission to the folder inside the document library. The PowerShell script uses the C# code for permission. The C# code will add mandatory Full Control access and break the inheritance. The code uses the lambda function to find the unique permission. Since PowerShell natively does not support lambda expression the C# code is embedded within the PowerShell

The full script is below

$cSharp = @”

using System;

using System.Security;

using System.Linq;

using System.Collections.Generic;

using Microsoft.SharePoint.Client;

namespace SPClient

{

public class Permission

{

private static string username = “”;

private static string password = “”;

private static string srcUrl = “”;

private static string[] groupNames = { “Team Site Members” };

private static string srcFolder = “folder path(/sites/dev/shared documents/folder1)”;

private static string permissionType = “Edit”;

private static string mandatoryGroupName = “Developer Owners”;

public static void ApplyPermission()

{

try

{

var securePassword = new SecureString();

foreach (char c in password)

{

securePassword.AppendChar(c);

}

using (var clientContext = new ClientContext(srcUrl))

{

Console.WriteLine(“Authenticating…” + srcUrl);

clientContext.Credentials = new SharePointOnlineCredentials(username, securePassword);

Web srcWeb = clientContext.Web;

Folder applyFolder = srcWeb.GetFolderByServerRelativeUrl(srcFolder);

clientContext.Load(srcWeb);

clientContext.Load(applyFolder,f=>f.ListItemAllFields.HasUniqueRoleAssignments);

clientContext.ExecuteQuery();

Console.WriteLine(“Connected.”);

Console.WriteLine(“Applying to folder : ” + srcFolder);

GroupCollection groups = srcWeb.SiteGroups;

clientContext.Load(groups);

clientContext.ExecuteQuery();

var myGroups = (from a in groupNames

from w in groups

where a == (w.Title)

select w).ToArray();

Console.WriteLine(“Groups…”);

var coordinator = (from a in groups where a.Title == mandatoryGroupName select a).FirstOrDefault();

RoleDefinitionCollection rdc = srcWeb.RoleDefinitions;

RoleDefinition myRole = rdc.GetByName(permissionType);

RoleDefinition coordinateRole = rdc.GetByName(“Full Control”);

clientContext.Load(rdc);

clientContext.Load(myRole);

clientContext.Load(coordinateRole);

clientContext.ExecuteQuery();

Console.WriteLine(“Role definitions…”);

if (!applyFolder.ListItemAllFields.HasUniqueRoleAssignments)

{

Console.WriteLine(“Breaking inheritance…”);

applyFolder.ListItemAllFields.BreakRoleInheritance(true, false);

}

else

{

Console.WriteLine(“Inheritance broken already…”);

}

var folderRoles = applyFolder.ListItemAllFields.RoleAssignments;

Console.WriteLine(“Applying the role assignments …”);

RoleDefinitionBindingCollection coordinateRdb = new RoleDefinitionBindingCollection(clientContext);

coordinateRdb.Add(coordinateRole);

RoleDefinitionBindingCollection collRdb = new RoleDefinitionBindingCollection(clientContext);

collRdb.Add(myRole);

//clientContext.Load(folderRoles);

//clientContext.ExecuteQuery();

folderRoles.Add(coordinator, coordinateRdb);

foreach (Group eachGroup in myGroups)

{

Console.WriteLine(“Applying Group: ” + eachGroup.Title);

folderRoles.Add(eachGroup, collRdb);

}

applyFolder.Update();

clientContext.ExecuteQuery();

Console.WriteLine(“Successfully applied”);

Console.Read();

}

}

catch(Exception ex)

{

Console.WriteLine(ex.Message);

//Console.Read();

}

}

}

}

“@

$assemblies = @(

“C:\Documents\PS\CSOM\Microsoft.SharePoint.Client.dll”,

“C:\Documents\PS\CSOM\Microsoft.SharePoint.Client.Runtime.dll”,

“System.Core”

)

Add-Type -TypeDefinition $cSharp -ReferencedAssemblies $assemblies

[SPClient.Permission]::ApplyPermission()