Category Archives: SharePoint

CSOM, PowerShell, SharePoint Search & SPFx

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.

 

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()

 

Document Library View with Nested Condition

The OOB SharePoint List / Document library view allows only flat OR / AND conditions to be applied to the columns. Think of a scenario where you want to get all documents modified on last 10 days from a selected list of people. This condition is difficult to achieve in OOB view creation. In this scenario the custom view with CAML query comes to the rescue. We can create a normal view in SharePoint and using the below PowerShell script we can update the existing view to use the nested condition.

The CAML query used to filter the document is like below


<FieldRef Name="Modified” Ascending=”FALSE” />


<FieldRef Name="Editor” /><Value Type="User“>senthamil<FieldRef Name="Editor” /> <Value Type="User“>venkat<FieldRef Name="Editor” /><Value Type="User“>amanda<FieldRef Name="Editor” /><Value Type="User“>arwen<FieldRef Name="Editor” />

<Value Type="User“>matthew<FieldRef Name="Editor” /><Value Type="User“>mcdonnel<FieldRef Name="Editor” /><Value Type="User“>ravi<FieldRef Name="Modified” /><Value Type="DateTime“><Today OffsetDays="-6” />

 

To achieve this first create a View in the SharePoint document library like a normal view with the name “LatestDocsByUsers”. Once you finished creating the view then download the PowerShell from this location and change the below variables

$username, $password, $srcList, $srcUrl and $view

In this case the $view = “LatestDocsByUsers”

The PowerShell will update the existing view with the above CAML Query.

The condition tree looks like below