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.

May 2, 2019

SharePoint: spHttpClient search query returns HTTP 500 when requesting Created field

Problem

When making SharePoint search query programmatically via REST API and including Created in selectProperties, query returns HTTP 500.

1
2
3
4
this.webPartContext.spHttpClient.get(
  `${this._searchUrl}?querytext='${query}'&selectProperties='Title,Path,Created'`,
  SPHttpClient.configurations.v1
)

When making the query via browser, it works nicely with and without Created in selectProperties.

Solution

Include specific ISPHttpOptions in the get call makes it work as described below.

In any case, it is good idea to include the odata=nometadata option in your REST calls to enable JSON Light whenever applicable to minimize the return payload. Usually you’re not interested in the metadata anyway.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// define _noMetaOpt
private _nometaOpt: ISPHttpClientOptions = {
  headers: { 'Accept': 'application/json;odata=nometadata', 'odata-version': '' }
};

// and call
this.webPartContext.spHttpClient.get(
  `${this._searchUrl}?querytext='${query}'&selectProperties='Title,Path,Created'`,
  SPHttpClient.configurations.v1,
  this._nometaOpt
)

October 31, 2018

SharePoint: Most Incoming E-Mail Settings for a list are missing

Problem

When attempting to configure incoming e-mail settings of SharePoint 2013/2016 on-premises site, the list specific settings only allow enabling the incoming e-mail, and the e-mail address, but not the other options, such as what to do with the attachments.

Below picture is in Finnish, but you will see there are only these two settings, and nothing else.

image

Thoughts

You’ve probably gone through all settings related to incoming email, and mails are in fact arriving to the Drop folder of the SMTP Server on the SharePoint server and are probably even being processed as the emails disappear from the Drop folder.

Solution

You have custom SPEmailEventReceiver registered (via Site feature) on the site you’re on. In this scenario, the Incoming E-Mail Settings of a list will not allow you to configure further settings related to incoming emails.

It does make sense, as it is the custom event receiver handling the emails, so it would make little sense attempting to configure anything more on a single list as it would have no effect. It would of course be nice if the settings page would indicate why the settings are missing.

September 6, 2018

openssl config failed: error:02001003 when building SharePoint Framework (SPFx) web part

Problem

When building SharePoint Framework (SPFx) web part, you get errors related to openssl, such as

openssl config failed: error:02001003:system library:fopen:No such process

openssl

Also, if you run commands such as “npn -v", you will get same warnings. Depending where you run the commands from, you get the error in PowerShell command line, or classic CMD prompt, or both.

These errors/warnings do not, however, break anything in usual development scenarions, so SharePoint Workbench (local and hosted) work fine.

Solution

Error is due to missing environment variable pointing to OpenSSL config file. You can find the config file from OpenSSL installation folder under bin folder, e.g., "C:\OpenSSL-Win64\bin\openssl.cfg".

For PowerShell (=if you run the commands in Visual Studio Code Terminal), run:

$Env:OPENSSL_CONF = "C:\OpenSSL-Win64\bin\openssl.cfg"

For CMD prompt, run:

SET OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg

However

I prefer instead just installing 32 bit version of OpenSSL and not having to worry about these things.

August 16, 2018

Azure functions: The remote runtime "~1" is not compatible with your local runtime "beta".

Problem

When trying to deploy Azure Functions from Visual Studio Code, you get error “The remote runtime "~1" is not compatible with your local runtime "beta".”

azfunc

As beta is not yet production ready, you may not want to update your Azure Functions in the portal to version 2, i.e., “beta”.

Solution

You probably created the Azure Function when you had version 2.0 of azure-functions-core-tools installed

npm i –g azure-functions-core-tools@core
when you should’ve installed the 1.0 version using
npm i -g azure-functions-core-tools

What you need to do is to go to VS Code workspace settings and change azureFunctions.projectRuntime from “beta” to “~1”. After that deployment works.

azfunc2

August 2, 2018

Cannot delete Azure Active Directory due to existing Enterprise Applications

Problem

After deleting all required objects from Azure AD, so you could delete it, the “Delete directory” validator still says “Delete all enterprise applications”, as there are custom Enterprise Applications preventing directory deletion.

1

Solution

Usually the reason is Microsoft Visual Studio Team Services Enterprise application. You can go to Properties, and flip “Enable for users to sign-in” to No, and it helps in some cases.

2

However, sometimes it is not enough, but you need to go and delete all Enterprise Applications via PowerShell (although many of them are internal Azure apps).

Command for logging in and deletion is:

Connect-AzureAD –TenantID <TENANT_ID>
#repeat the following line for EACH Enterprise Application, some will throw error, but ignore it
Remove-AzureADServicePrincipal –ObjectId <OBJECT_ID_OF_ENT_APP>

Then with your web browser, log out from the Azure portal, and log back in, and you should be able to delete the Azure AD using browser.

Do note that Get-AzureADServicePrincipal | Remove-AzureADServicePrincipal didn’t work for some reason, and I needed to do the removal one by one.