February 4, 2020

SharePoint: Web part SPUserCodeNoAvailableServersFoundException error

Problem

Web part is not loading, you see exception SPUserCodeNoAvailableServersFoundException.

Solution

Start “Microsoft SharePoint Foundation Sandboxed Code Service”.

  1. Go to Central Admin
  2. Go to System Settings –> Manage services in this farm
  3. At “Microsoft SharePoint Foundation Sandboxed Code Service” click “Enable Auto Provisioning”

January 30, 2020

SharePoint: Setting list view specific persisted spcolumnsize programmatically

Problem

I needed to set default list view column widths programmatically on SharePoint Online modern list. I was using PnPjs to create and configure the list.

Thoughts

In modern SPO list view you can change column width, it is then temporarily stored in browser Local Storage as spcolumnsize-unsaved-VIEWGUID. However, you also have the option of saving it into View somehow, as asterisk (*) appears next to view name on SharePoint and you can "Save View As" to persist the column width somewhere. After saving the view even if you remove the spcolumnsize-unsaved-VIEWGUID Local Storage key, and refresh the page, it comes back as spcolumnsize-VIEWGUID, so clearly it is stored somewhere in SharePoint.

Solution

Column widths are persisted in ListViewXml view property inside ColumnWidth element as FieldRef elements. Do note that the FieldRef Names must be column display names, NOT internal field names. I didn’t implement fancy XML parsing, just injected the ColumnWidth element at the end just before ending View tag.

// set field widths
let lv: any = await list.defaultView.select('ListViewXml').get();

let lvXml: string = lv.ListViewXml.replace(
'</View>', '<ColumnWidth><FieldRef Name="Column title 1" width="370" /><FieldRef Name="Some other column" width="90" /></ColumnWidth></View>');

await list.defaultView.setViewXml(lvXml);

December 12, 2019

SPFx: Changing Folder Content Type using PnPjs

Task

Needed to create Folders with custom Content Type in SharePoint document library from my SPFx web part, as there was a need to add some custom fields, such as Description, to the Folder item.

Solution

This one took a few hours to figure out, you need to do it in few steps as you cannot change the content type of a folder using sp.web.folders…update as REST API doesn’t allow ContentTypeId parameter when updating Folder content types, and you will get error:

“The property 'ContentTypeId' does not exist on type 'SP.Folder’. Make sure to only use property names that are defined by the type”

Also if you would use …folder.getItem(), it will fail if folder has special characters.

  1. Create folder as normal Folder
  2. Get list item ID of the folder
  3. Update folder as a list item
let etfn = await sp.web.getList(listUrl).getListItemEntityTypeFullName();

// first create folder
let far: FolderAddResult = await sp.web.folders.add(listUrl + '/' + targetParentFolderName + targetFolderName);

// then get list item ID of the folder
let fData: any = await sp.web.getFolderById(far.data.UniqueId).select('ID').listItemAllFields.get();            

// then get folder as list item
let item: Item = sp.web.getList(listUrl).items.getById(fData['ID']);

await item.update({
    ContentTypeId: 'CUSTOM_FOLDER_CONTENTTYPE',
    PF_FolderDescription: 'Some description...'
}, '*', etfn);

September 17, 2019

Office Online Server: X-WOPI-ServerError "Verifying signature failed"

Problem

After migrating from old OOS (WAC) server to new one, integration between SharePoint and Office Online Server stopped working, and no documents could be opened in browser.

Looking at the network traffic using WireShark, you see X-WOPI-ServerError "Verifying signature failed".


Solution

  1. Ensure HTTPS (TCP 443) flows from SP servers to OOS
  2. Run Update-SPWOPIProofKey -ServerName YOUR_OOS_URL
This will update the required keys in SharePoint and documents can again be opened in browser.

September 4, 2019

SharePoint Online: Hiding "Shared with Us" link in Modern Menu

Problem

For apparently nearly 3 years, people have wanted to hide the “Shared with Us” menu item that is displayed in the Current navigation on modern SharePoint list views. The menu item is injected as 4th item on the menu on sites that are Group based. Item doesn’t exist on traditional Team sites although they would be modern.



Thoughts

There is no way to hide it by modifying the Current navigation, nor by disabling any feature.

Solution

Best I came up with was to inject CSS on all tenant sites, and hide it with simple CSS style. It’s not perfect solution, as the CSS is injected using JavaScript meaning when page is loaded, it will momentarily display the “Shared with us” link before the JavaScript is loaded and CSS is injected.

Good thing, though, is that it does work across all sites with just one deploy and can be easily modified.

Let’s do this

  1. Clone and build my fork (https://github.com/jpalo/react-application-injectcss) of the handy CSS injection SPFx extension made originally by hugoabernier, thanks Hugo!
    - Hugo’s latest version is for SPFx 1.8.0, mine is 1.9.1, so in case you want to use the latest (as of writing) SPFx version, use my fork.
    - My code also assumes the custom.css is in /sites/cdn/Style%20Library/custom.css, but that is easily modified in case you want to use another location.
  2. Before deploying the .sspkg to the tenant, ensure /sites/cds site collection exists, and upload the custom.css from the of the SPFx project to /sites/cdn/Style%20Library/custom.css
  3. Depending on the user base of your tenant, you will need to assign proper Read permissions to the /sites/cdn site collection for all users (and possibly Guests) to be able to read the custom.css file

May 22, 2019

SharePoint: Determining if library root level folders have broken permission inheritance using PnP PowerShell

This simple script can be used to determine status of permission inheritance of document library root level folders.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$siteUrl = "https://mytenant.sharepoint.com/sites/somesitecollection"
Connect-PnPOnline -Url $siteUrl -UseWebLogin
$context = Get-PnPContext 

$list = Get-PnPList "SomeLibrary"

$folders = $list.RootFolder.Folders
$context.Load($folders)
$context.ExecuteQuery()

foreach($folder in $folders)
{
  if($folder.ItemCount -gt 0)
  {    
    $f = Get-PnPFolder -Url $folder.ServerRelativeUrl -Includes ListItemAllFields.RoleAssignments, ListItemAllFields.HasUniqueRoleAssignments

    $context.Load($f)
    $context.ExecuteQuery()

    Write-Host $f.ServerRelativeUrl -> $f.ListItemAllFields.HasUniqueRoleAssignments
  }
}

May 20, 2019

SharePoint: Update List Content Type via REST from SPFx web part

Task

I needed to set ReadOnly property of a SPList Content Type from my SPFx web part. I’m using @pnp/sp library, but it doesn’t support modifying existing Content Types.

Solution

Changing the ReadOnly property of an existing list content type is possible using REST, but I had some troubles finding out correct set of HTTP body and header payloads. Working code can be found below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
const spOpts: ISPHttpClientOptions = {
  headers: { 'Accept': 'application/json;odata=verbose', 'X-HTTP-Method': 'MERGE', 'odata-version': '3.0' },
  body: JSON.stringify({
    __metadata: {
      type: 'SP.ContentType'
    },            
    ReadOnly: false
  })
};

let oldCt: ContentType = list.contentTypes.getById('0x01CONTENTTYPEID');

await this.props.context.spHttpClient.post(
  oldCt.toUrlAndQuery(),
  SPHttpClient.configurations.v1,
  spOpts
);


Thoughts

For later reference when investigating similar issues, here’s a collection of error messages depending what Header parameter is missing or invalid.

Without this header propertyYou got error
'Accept': 'application/json;odata=verbose' The property '__metadata' does not exist on type 'SP.ContentType'. Make sure to only use property names that are defined by the type.

Note: This is not required, as odata will be verbose by default unless you have manually set it to, e.g., nometadata. I usually set it to nometadata to improve performance as verbose metadata results of REST calls are not usually required. odata=minimalmetadata is not enough.
'X-HTTP-Method': 'MERGE' The parameter __metadata does not exist in method GetById.
'odata-version': ‘3.0’ Parsing JSON Light feeds or entries in requests without entity set is not supported. Pass in the entity set as a parameter to ODataMessageReader.CreateODataEntryReader or ODataMessageReader.CreateODataFeedReader method.

Note: By default, odata-version will be 4.0, and it doesn’t work here.