Thursday, July 18, 2019

Problem with Copy-PnPFile cmdlet and File Not Found error

Sharepoint PnP PowerShell library has many useful commands which simplify scripting against Sharepoint Online. One of them is Copy-PnPFile which allows to copy file from one document library to another. Source and target doclibs may be even located in different site collections in the same tenant.

One of example of Copy-PnPFile (basically 1st example) says that it is possible to copy single file like that:

Copy-PnPFile -SourceUrl Documents/company.docx -TargetUrl /sites/otherproject/Documents/company.docx

Unfortunately currently it gives File not found error. Looks like there is a bug in Copy-PnPFile which prevents it from working correctly – it is also described in this StackOverflow thread which was created couple of days ago: Copy-PnPFile returns File Not Found.

The only working way which I’ve found so far is to copy whole root folder:

Copy-PnPFile -SourceUrl Documents -TargetUrl /sites/otherproject/Documents -SkipSourceFolderName

It will copy all files from Documents doclib to Documents doclib on another site collection /sites/otherproject. However it will also try to copy OTB list view AllItems.aspx as last file and it will give error that AllItems.aspx already exists in target doclib. In order to ignore this error I used the following solution:

$error = $null
Copy-PnPFile -SourceUrl Documents -TargetUrl /sites/otherproject/Documents -SkipSourceFolderName -ErrorAction SilentlyContinue -ErrorVariable error
if ($error -and !$error.Exception.Message.ToLower().Contains("allitems.aspx")) {
    throw $error

I.e. it will throw error only if message doesn’t contain allitems.aspx occurrence. Hope that it will help someone.

Monday, July 15, 2019

Problem with not editable host.json file for Azure function app

Some time we need to manually modify content of host.json file of Azure function app (e.g. to change logging settings). In order to do that you need to go to Azure function app > Platform features > Function app settings > host.json. However you may face with situation that textarea which stores content of host.json will be readonly:

In this case change Function app edit mode setting on the same page from “Read only” to “Read/Write”. After that you will be able to edit content of host.json file for you Azure function app:

Friday, July 12, 2019

Get all Azure AD groups where current user is a member transitively via Graph API

As you probably know we may get all groups where user is member using memberOf endpoint:

GET /users/{id | userPrincipalName}/memberOf

This endpoint returns only those groups where user was added as direct member. I.e. if user was added to GroupA and this GroupA was then added to GroupB – it will return only GroupA but not GruopB. However we often need to get all groups where user is member transitively. Fortunately it is also possible with another endpoint getMemberGroups:

POST /users/{id | userPrincipalName}/getMemberGroups

Until recently it was available only in Graph API itself – not in .Net Graph client library. Fortunately starting with 1.16 version Microsoft.Graph.User class got new property TransitiveMemberOf propery:

Using this property we may get all groups where user is member transitively. It supports paging so in order to get all groups we also need to iterate through pages. Here is the code example which does that:

private static List<Guid> GetUserGroupsTrasitively(string userPrincipalName)
  var graph = new GraphServiceClient(new AzureAuthenticationProvider());
  var groups = graph.Users[userPrincipalName].TransitiveMemberOf.Request().GetAsync().Result;
  if (groups == null)
   return new List<Guid>();

  var result = new List<Guid>();
  while (groups.Count > 0)
   foreach (var group in groups)
    result.Add(new Guid(group.Id));

   if (groups.NextPageRequest != null)
    groups = groups.NextPageRequest.GetAsync().Result;

  return result;
 catch (Exception x)
  // error handling

Monday, July 1, 2019

Sharepoint MVP 2019

I got very exciting email from MS today that I’ve got MVP award in Office Apps & Services category. Although it is 9th award for me it definitely has own place in my professional life and I’m very glad that MS recognizes my contribution to community life with this award. Last year a lot of work was done related with MS Graph API and OfficeDevPnP. Many issues, workarounds and solutions were discussed during last year on forums, in blog posts comments, github issues, etc. Also I continue maintenance of Camlex library which simplifies creation of dynamic CAML queries for developers. Nowadays new technologies appear very often and they allow us to do such things which were not possible before. This is great but developers’ life don’t become easier because of that – we get new and new challenges in our work every day. From this perspective community role is crucial – I can’t say how many times I by myself found solutions for technical challenges in blog posts, forums, code samples, etc. Knowing on practice how important this work is I also try to share my findings, ideas and solutions with community. Thank you MS and thank you dear readers of my blog for being with me this year. Looking forward for the new year with it’s own interesting challenges and inventive solutions.