How can I change the View of a SharePoint Online folder programmatically? - sharepoint-online

I have a powershell script that creates Folders in SharePoint online.
I'm using Add-PnPFolder to do so.
By default the new folder view is sorted by Name.
I wish to change the default view so that it is sorted by the field Created.
Manually this can easily be done. But programmatically I have no clue how to change the view of a PnPFolder.
Here's the part of the code where I create the folder...
Connect-PnPOnline -ClientId $SPO_AppId -ClientSecret $SPO_AppSecret -Url $siteUrl
$connection = Get-PnPConnection
if ($connection)
{
Add-PnPFolder -Folder /Team/Acquisition -Name Approvals -Connection $connection
}
Get-PnPView only works on PnPLists, not on PnPFolders unfortunately.

The order of the items displayed in view is configured in the view property, not in item property.
Code example to change the sorting property of a view:
$Context = Get-PnPContext
$view=Get-PnPView -List "Documents" -Identity "2B0E08F9-39AC-4553-9343-FDDF3551F77A"
$Context.Load($View)
$Context.ExecuteQuery()
$Query= "<OrderBy><FieldRef Name='Created' /></OrderBy>"
$View.ViewQuery = $ViewQuery
$View.ViewQuery = $QUERY
$View.Update()
$Context.ExecuteQuery()

Related

Is there a nicer way to export Azure DevOps project's Templates (fields and states)?

I use 'witadmin listfields' command for whole collection, but wondering if I could scale fields/states just to a single project?
The reason behind this: sometimes I migrate TFS project to AzureDevOps existing project. And collecting data about fields takes a lot of manual work. Wondering about the automation of this process...
Many thanks!
You can check out the rest api to get the fields/states of a project. See below:
Work Item Types Field - List
GET https://{instance}/{collection}/{project}/_apis/wit/workitemtypes/{type}/fields?api-version=4.1
Work Item Type States - List
GET https://{instance}/{collection}/{project}/_apis/wit/workitemtypes/{type}/states?api-version=4.1-preview.1
For below example, call above rest apis in powershell scripts:
[string]$userName = 'domain\username'
[string]$userPassword = 'password'
# Convert to SecureString
[securestring]$secStringPassword = ConvertTo-SecureString $userPassword -AsPlainText -Force
[pscredential]$credOject = New-Object System.Management.Automation.PSCredential ($userName, $secStringPassword)
$uri = "http://{instance}/{collection}/{project}/_apis/wit/workitemtypes/Bug/fields?api-version=4.1"
$invRestMethParams = #{
Credential = $credOject
Uri = $uri
Method = 'Get'
ContentType = 'application/json'
}
Invoke-RestMethod #invRestMethParams

How to generate a ClientContext from SiteId in SharePoint Online?

I have a SiteId and I want to generate a ClientContext to fetch all the groups of that particular site. But I am not able to find a way to generate a ClientContext from the SiteId same we do in SharePoint on-premises.
Is there a way to generate a ClientContext from SiteId in SharePoint Online or we need the URL only?
I want to achieve something like this:
using(var context = new ClientContext(new GUId(siteId))
{
//TODO
}
You can get your ClientContext in two steps:
search the site by its ID using the search API
create a client context using the site's URL
Here's some PowerShell doing exactly this. I'm using the PnP Cmdlets out of convenience, similar results can also be achieved using plain CSOM.
# this is your site's ID
$siteId = "a20d2341-1b4f-47ed-8180-24a5c31adfa9"
# basically any known site URL - the root is probably fine
$anySiteUrl = "https://<yourtenant>.sharepoint.com"
$credential = Get-Credential
Connect-PnPOnline –Url $anySiteUrl –Credentials $credential
# search for site by ID
$site = Submit-PnPSearchQuery -Query "SiteID:$siteId AND ContentClass=STS_Site"
if ($site.ResultRows.Count -eq 1)
{
# URL to use for "real" connection
$siteUrl = $site.ResultRows[0].Path
Connect-PnPOnline –Url $siteUrl –Credentials $credential
$currentSite = Get-PnPSite
# and there is your ClientContext
$ctx = Get-PnPContext
$web = $currentSite.RootWeb
$ctx.Load($web)
$ctx.Load($web.SiteGroups)
$ctx.ExecuteQuery()
# here are your groups
$web.SiteGroups
}
(Note: you must install the SharePointPnPPowerShellOnline PowerShell module for this code to run.)

Get user details from SharePoint with PowerShell

I'm using this PowerShell script to get site owners:
$siteUrl = Read-Host "enter site url here:"
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication
foreach($site in $spWebApp.Sites)
{
foreach($siteAdmin in $site.RootWeb.SiteAdministrators)
{
Write-Host "$($siteAdmin.ParentWeb.Url) - $($siteAdmin.DisplayName)"
}
$site.Dispose()
}
$rootSite.Dispose()
I want that it will print some details of the site owner like phone number and email. How can I achieve that?
You have two choices I think. Access the SPUser properties or get information from active directory.
In the first case, are you not able to access the properties as you did for DisplayName? I mean if you have a SPUser object to get the email just use:
write-output "$($siteAdmin.Email)"
For information about to get the user properties from active directory, you can easily implement the solution provided in the following question. It worked fine for me.
Hope this helps
EDIT with improvement
Standing from MS Documentation you have some properties avaialble, see SPUSer Members. FOr example you have not phone.
To get something from the active directory try to change the following function so that it returns the attributes you need (tested on windows 2k8 server):
function Get-AD-Data {
$strFilter = "(&(objectCategory=User))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
$objSearcher.FindAll() | select #{L="User";E={$_.properties.displayname}},
#{L="Department";E={$_.properties.department}},
#{L="MemberOf";E={$_.properties.memberof}}
}
This function returns all users from AD along with the selected attributes. To get information from a specific user you would use (I guess):
$ad_userdetails = Get-AD-Data | ? {$_.user -eq $siteAdmin.Name}
Cheers

Update SharePoint Default Alternate Access Mapping Programmatically

I'm enabling HTTPS on my IIS server where I have SharePoint Services 3.0 installed and I'd like to programatically update the default alternate access mappings for a single web application and my central administration instance (both on the same machine). Here's the code I have so far (Powershell), it adds a mapping for HTTPS but I get and error when trying to remove the original one.
Here's my code:
[void][system.reflection.assembly]::LoadWithPartialName("Microsoft.Sharepoint")
$SPWebServiceCollection = new-object Microsoft.SharePoint.Administration.SPWebServiceCollection ([Microsoft.SharePoint.Administration.SPFarm]::Local)
foreach ($SPWebService in $SPWebServiceCollection) {
foreach ($webApplication in $SPWebService.WebApplications) {
Write-Host ('Updating {0}' -f $webApplication.Name)
foreach ($alternateUrl in $webApplication.AlternateUrls) {
$incomingUrl = [System.URI] $alternateUrl.IncomingUrl
$newURL = 'https://{0}{1}' -f $incomingUrl.Authority, $incomingUrl.PathAndQuery
$newAltURL = New-Object Microsoft.SharePoint.Administration.SPAlternateUrl ($newURL, $alternateUrl.UrlZone)
$webApplication.AlternateUrls.Add($newAltURL)
$webApplication.AlternateUrls.Update($true)
$webApplication.AlternateUrls.Remove($alternateUrl) #Throws Exception
$webApplication.AlternateUrls.Update($true)
}
}
}
Here is the error I get when I try to remove the original:
Exception calling "Remove" with "1" argument(s): "An object in the SharePoint administrative framework, "SPAlternateUrlCollection Name=SharePoint - 1000 Parent=SPFarm Name=SharePoint_Config_8ddd3701-a332-4e79-98e4-fa11c1b6c17c", could not be deleted because other objects depend on it. Update all of these dependants to point to null or different objects and retry this operation. The dependant objects are as follows:
SPWebApplication Name=SharePoint - 1000 Parent=SPWebService
However, i'm not sure how to do what the exception suggests.
Ah... it looks like you are trying to remove the URL the Webservice is using...
It turns out there's another method for the exiting default entry that I overlooked:
$webApplication.AlternateUrls.SetResponseUrl($newAltURL)
[void][system.reflection.assembly]::LoadWithPartialName("Microsoft.Sharepoint")
$SPWebServiceCollection = new-object Microsoft.SharePoint.Administration.SPWebServiceCollection ([Microsoft.SharePoint.Administration.SPFarm]::Local)
foreach ($SPWebService in $SPWebServiceCollection) {
foreach ($webApplication in $SPWebService.WebApplications) {
Write-Host ('Updating {0}' -f $webApplication.Name)
foreach ($alternateUrl in $webApplication.AlternateUrls) {
$incomingUrl = [System.URI] $alternateUrl.IncomingUrl
$newURL = 'https://{0}{1}' -f $incomingUrl.Authority, $incomingUrl.PathAndQuery
$newAltURL = New-Object Microsoft.SharePoint.Administration.SPAlternateUrl ($newURL, $alternateUrl.UrlZone)
$webApplication.AlternateUrls.SetResponseUrl($newAltURL)
$webApplication.AlternateUrls.Update($true)
}
}
}

Manage views for content types (or add a view to multiple lists)

I'm surprised that I cannot find on the net a solution where I could manage views for content types. Do I really have to visit each task list with my browser to add/modify a view?
Is there any solutions available that would allow me to just define a view for content type and thus make this view available on all lists where content type is?
Directly speaking, no, a view cannot be assigned to a content type. Lists are what hold an actual view collection, and the corresponding aspx page that is created with it. A view also has a dependent existence with its list: you cannot have a view that is not associated with a list. There is also no "event handler" for adding a content type to a list, either, so you can't have some automatic process that occurs whenever you add a content type to the list (and it would be cumbersome anyway as you'd have to attach the event handler to the list in the first place!).
This isn't to say you have to manually muck about in the UI to accomplish the task, though. Using the object model in something like a custom code workflow, you can sweep across your entire SPWeb and create a new view on each list that has the specified content type. All you need is a workflow with a single code activity, which iterates across all of the SPLists in SPWeb.Lists, and check if that SPList has the content type with the same name as your target content type. If it does, create a new SPView with the parameters you need. Since you cannot simply create one SPView and clone it, as an SPView must be associated with a list and cloning an SPView just clones it onto the same list, you'll have to run the whole SPView creation in each loop. But you only have to write it once, it's the system that'll have to run it multiple times. And by heavens, it'll certainly get that done a lot more productively than if you had to dance about in the UI for a few hours.
Simply run the workflow any time you need to reassert the existence of that SPView.
I found this solution in c#, however I have not yet tested it.
I will test it in the future, and update this if necessary.
Apparently, it is for SharePoint 2010, however it may work in later versions too.
private void CreateView(string strViewName)
{
try
{
string fieldName = //Get Field Internal Name
var docquery = "<Where><Eq><FieldRef Name='" + fieldName.ToString() + "' /><Value Type='Choice'>" + strViewName.ToString() + "</Value></Eq></Where>";
System.Collections.Specialized.StringCollection viewFields = new System.Collections.Specialized.StringCollection();
viewFields.Add("Type");
viewFields.Add("Name");
viewFields.Add("Modified");
viewFields.Add("Modified By");
viewFields.Add(fieldName.ToString());
oViewCollection.Add(strViewName, viewFields, docquery, 100, true, false);
web.Update();
}
catch (Exception e)
{
throw new SPException(e.Message.ToString());
}
}
I also found this solution in PowerShell...
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA silentlycontinue
#Title View
$viewTitle = "Sort by modified date"
#Add the column names from the ViewField property to a string collection
$viewFields = New-Object System.Collections.Specialized.StringCollection
$viewFields.Add("DocIcon") > $null
$viewFields.Add("LinkFilename") > $null
$viewFields.Add("Modified") > $null
$viewFields.Add("Editor") > $null
$viewFields.Add("FileSizeDisplay") > $null
#Query property
$viewQuery = "<OrderBy><FieldRef Name='Modified' Ascending='FALSE'/></OrderBy>"
#RowLimit property
$viewRowLimit = 50
#Paged property
$viewPaged = $true
#DefaultView property
$viewDefaultView = $false
$ListsToUpdate = #()
$App = Get-SPWebApplication http://....
foreach ($Site in $App.Sites)
{
foreach ($Web in $Site.AllWebs)
{
foreach ($List in $Web.Lists)
{
if($List.BaseType -eq "DocumentLibrary" -and $List.Title -eq "Documents" )
{
$ListsToUpdate += $Web.Lists[$List.Title]
}
}
}
}
foreach($List in $ListsToUpdate)
{
Write-Host $List.Title
#Create the view in the destination list
$newview = $List.Views.Add($viewTitle, $viewFields, $viewQuery, $viewRowLimit, $viewPaged, $viewDefaultView)
}

Resources