Friday, April 21, 2017

Creating a .pnp provisioning template file

SharePoint Patterns and Practices

After my demo on the PnP screen cast where I showed a provisioning solution based on PowerShell and Azure web jobs, I’ve had some questions about how you go about creating the .pnp files we use for provisioning templates.

There are basically two options, and it’s quite easy. For full samples run Get-Help <command> –Examples on the command lets. If you want to use code instead of PowerShell, look at the PowerShell code in github and see how it’s all implemented.

Generate .pnp file from a site

Connect to the site, and then run:

PS:> Get-PnPProvisioningTemplate -Out template.pnp

By naming the output .pnp, you get a .pnp file instead of and .xml file.

Generate .pnp file from a template xml file

This works for both a single .xml file, or one referencing artifacts.

Make sure the .xml file and all artifacts are stored in a folder. Then run:

PS:> Convert-PnPFolderToProvisioningTemplate -Out template.pnp -Folder c:\temp

It’s important that the .pnp file has the same name as the .xml file inside the folder, due to convention when applying the template, as you can have multiple .xml files in a complete template referenced with <xi:include> statements.

Improved navigation for Office 365 Groups

A colleague showed me yesterday that now you can actually navigate from a Group site to any other resource. Just click the site title, and a menu appears. I have no idea when this was rolled out, and kind of difficult to discover – but hey, it’s Friday, so let’s celebrate that things are improving making life easier.


Wednesday, April 19, 2017

Why the new Microsoft is cool–rapid bug fixing

I had a customer report that the label when closing a card in Planner gave the wrong impression of the actual action. The term used was “Forkast”,(English “Dismiss”). The labeling gives the impression that whatever changes you have made are not saved, which is not the case as all changes are auto saved.

Norwegian text when closing a task card in Planner

I reported this to Microsoft in a translation forum I’m part of at Linked-in, and lo and behold, one week later Microsoft changed the label in all languages, where the English label now is “Close”. “Close” communicates the correct action a lot better indeed :D

A tiny step, but a one week turnaround on this is awesome!


Wednesday, April 12, 2017

SharePoint PnP Webcast – Provisioning with PnP PowerShell and Azure WebJobs

I had the pleasure of doing this web cast with Vesa Juvonen recently where I do a demo of how you can set up a pretty simple provisioning solution to let users order new team sites in SharePoint Online using an order list, and an azure web job to do the heavy lifting. A simple solutions with only two technical components, a SharePoint site and an Azure web job using PnP PowerShell.

The complete sample is located at the PnP repo ( and contains everything you need to get up and running.

PnP webcast post:

I’m currently doing the same approach for Office 365 Groups with a customer, so watch out for a sample on this later as well.

Wednesday, April 5, 2017

I’ve been a podcast guest twice in the past month

Curious on what I sound like if you’ve never met me? Now is your chance.

I was recently a guest at Tobias Zimmergren’s Rencore Tech Talk episode 6, where we talked about PnP provisioning and how you can configure SharePoint sites.

And I also was a guest on episode 120 of the Office 365 Developer Podcast with Richard diZerega and Andrew Coates, where we talked about development, provisioning and more.

Friday, March 31, 2017

Context to function, Function to context – confused already? (a story about Classic sites, Office 365 Groups, Teams, and navigation)

If you don’t care about the backdrop or thought process, skip to the end about how I envision Office 365 Groups to help organizations in the future.

Once upon a time someone came up with the idea that using a web site was a good way for people to collaborate at work. Thus, SharePoint was born, and many office workers have over the years learned to love and hate SharePoint and all that comes with it.

The SharePoint team site was a place to go to collaborate and find resources related to a project, department, customer, special interest group; and the list goes on. It was the landing page for a particular context. On the front page of the site you could see documents, links to external resources and other useful information. You could even have a news feed and later Yammer embed to bring enterprise social into the fold. And this is very much what you see in present day SharePoint use as well. Dashboards and pages with contextual information en masse.

Wednesday, March 29, 2017

SharePoint Search Query Tool v2.6

It’s been a year and figured I’d put out a small fix release.

The tool should now work properly with ADFS, UAG and TMG. We’ve also fixed the issue with multiple SPO tenants, where the application now prompts you each time without any cookie crumbs sticking around. You can even switch tenants without closing the tool.

As for new features I added a “Copy to clipboard” button which copies the raw JSON/XML of the result to the clipboard. Works a lot better than selecting from the raw tab.



Tuesday, March 28, 2017

Restoration of a deleted Office 365 Group is launched!

Johan Åslund tweeted about a support article showing how to restore an Office 365 Group using Powershell. This is a long wanted feature, and you will be able to restore a soft deleted Group within 30 days of it being deleted. Recovering the whole Group. Later the functionality will be available in the Office 365 admin UI.

The article is dated March 16th, so seems they have slipped this awesome news by us on the back channel. The news is also listed on the Office 365 Roadmap as launched.

If you have waited on this before recommending usage of Groups, now there is no stopping you.

You cand find the support article at:

Monday, March 27, 2017

Controlling Groups creation in a tenant using the AAD V2 PowerShell module

Recently I wrote a post how to set classification on Office 365 Groups. If you want to restrict or govern who can create Office 365 Groups, you can basically use the same script. I’ve adapted the steps from Wictor Wilén’s post which uses the old commandlets.

If you want total lockdown except for tenant admins, remove the GroupCreationAllowedGroupId lines, but I recommend setting this to some IT related AAD group to allow some group creation. For a customer we have a custom Groups ordering process, which works regardless of policy settings, allowing full control of Groups creation.

A quick note, at the time of this writing you have to use the preview commandlets as the released one is missing the settings commands needed.

Find-Module AzureADPreview #ensure it's in the list
Install-Module AzureADPreview
Import-Module AzureADPreview
$credentials = Get-Credential
Connect-AzureAD -Credential $credentials

#AD group which should be allowed to create groups
$group = Get-AzureADGroup -SearchString "-Group creators-"
if($group -eq $null) {
    Write-Host "You need to change the script to limit groups creation to a specific AAD group" -ForegroundColor Red

# Try to fetch settings
$policySetting = Get-AzureADDirectorySetting | Where-Object {$_.DisplayName -eq "Group.Unified"}

if ($policySetting -eq $null) {
    $template = Get-AzureADDirectorySettingTemplate | Where-Object {$_.DisplayName -eq "Group.Unified"}
    # Create the settings object from the template
    $settings = $template.CreateSettingsObject()

    # Use this settings object to prevent others than specified group to create Groups
    $settings["EnableGroupCreation"] = $false
    $settings["GroupCreationAllowedGroupId"] = $group.ObjectId
    # (optional) Add a link to the Group usage guidelines
    $settings["UsageGuidelinesUrl"] = ""

    $policySetting = New-AzureADDirectorySetting -DirectorySetting $setting
else {
    $policySetting["EnableGroupCreation"] = $false
    $policySetting["GroupCreationAllowedGroupId"] = $group.ObjectId
    $policySetting["UsageGuidelinesUrl"] = ""

    Set-AzureADDirectorySetting -ObjectId $policySetting.Id -DirectorySetting $policySetting

Tuesday, March 21, 2017

Why you need to pay attention to Office 365 message center updates (Auto creation of Direct Reports Office 365 groups coming)

Image result for mayhem
[Update 2017-03-22]
As there was a community outcry against this rollout, Microsoft has decided to limit the rollout. You can read about it in MC96611. This means that if you have the message MC94808, then you are eligible for the rollout. If not, then wait and see what happens in the future.

We listened to your concerns and have decided to limit the rollout of this feature to a smaller set of customers (notified via MC94808) whom we will work with directly to ensure feedback is considered, and the feature has a positive impact. We thank you all for your constructive feedback, we have learned a few lessons and look forward to continued Group innovations in the future.

There was a news item (MC96611) which peeked my interest in the Office 365 message center the other day about auto creating Office 365 Groups for “direct reports”. The support article states:
Beginning in April 2017, managers who have 2-20 direct reports, do not already have a direct reports group, and have permissions to create groups in Outlook, will automatically have a private group created for them with their direct reports. The manager will be added as an owner, and the direct reports of the manager will be added as members by default. The group will be named "<Manager's Name>'s direct reports", but that can be edited.
From the message center we get the following information:

What do I need to prepare for this change?

If you are looking forward to this, there is no action you need to take. Get yourself familiar with Office 365 Groups, update your user training, and notify your helpdesk, as needed.
If you would like to leave Office 365 Groups enabled for your organization but turn off direct reports groups creation, we have provided controls to enable and disable. Please click Additional Information to learn more.


I can just imagine all the larger companies out there missing this information suddenly getting a plethora of AAD groups which the IT dude will just faint over. So the real action here I suspect is to head over to the support article and read how to opt-out from this change.

There's a long thread on the topic over at the Microsoft Tech Community if you want to chime in.

Monday, March 20, 2017

Controlling invitation of external members to an Office 365 group programmatically via the Microsoft Graph

Microsoft has a support article explaining how to change the allow or deny policy of inviting external members to an Office 365 Group via PowerShell. This is all nice, but it doesn’t scale well in an automation scenario.

In my current project the default setting is to allow externals outside the organization to be invited, but through a custom groups order form, you can choose to block external parties – which is useful for internal only projects.

So how do you go about this?



As I’m doing automation using Office 365 app tokens via the Microsoft Graph, the following scopes are needed when working with Groups and Directory objects (and remember to admin consent) :
  • Group.ReadWrite.All
  • Directory.ReadWrite.All
  • User.Read.All (needed when adding owners/members)

Applying the template

I followed the support article for PowerShell which tells you to apply a template named Group.Unified.Guest which has the id 08d542b9-071f-4e16-94b0-74abb372e3d9 to the group, setting AllowToAddGuests to true or false, depending on if you want to allow external members or not.

A word of caution: The functionality of working with directory objects via the Microsoft Graph is only available at the beta end-point at the time of writing. But as long as it works I’m good to go, and I’ll monitor if the API changes and when it moves to GA.

The code uses Office PnP PowerShell to connect to the Microsoft Graph, creates a new Office 365 group, retrieves the app access token which is then used in a manual web request to apply a policy to the newly created group. Adapting the sample to your scenario should be easy enough, as it’s the web request applying the actual policy. If you're curious, we're using Azure web jobs to poll the order list, and uses PnP PowerShell like below for the automation.

#Connect to the Graph
Connect-PnPMicrosoftGraph -AppId $appId -AppSecret $appSecret -AADDomain

#Create a new group
$group = New-PnPUnifiedGroup -MailNickname $mailAlias -DisplayName $displayName -Description $description -IsPrivate:$private -Owners $owner -Members $members

#Get the access token
$token = Get-PnPAccessToken

#Prepare headers
$headers = @{"Content-Type" = "application/json" ; "Authorization" = "Bearer " + $token}

#The directory template to set the policy
$templateDeny = @"
  "templateId": "08d542b9-071f-4e16-94b0-74abb372e3d9",
  "values": [
      "name": "AllowToAddGuests",
      "value": "False"

#Graph URL to add settings to the group
$url = "$($group.GroupId)/settings"

#Apply the template, and wait for a 204
Invoke-WebRequest -Method Post -Uri $url -Headers $headers -Body $templateDeny

Thursday, March 16, 2017

Microsoft Graph adds SharePoint endpoint for Groups in the beta branch

I’m calling the Microsoft Graph with Office 365 groups these days and I stumbled upon a new SharePoint endpoint for Groups.

If you call:

you will get the following information back, listing the site name and URL – a better approach compared to using the /drive/root/webUrl endpoint as you don’t have to strip anything.

    "@odata.context": "$metadata#groups('821b0970-fae7-4640-bb22-5d091fd17a33')/sharepoint/site/$entity",
    "createdDateTime": "2017-03-16T16:55:39.19Z",
    "description": "",
    "id": "42d1e3d3-a645-4388-a217-4d88380802df,de4b0a91-5caa-4732-a530-67cfb2b0c42d",
    "lastModifiedDateTime": "2017-03-16T11:00:08Z",
    "name": "project-govtest",
    "webUrl": "",
    "root": {},
    "siteCollection": {
        "hostname": ""
    "siteCollectionId": "42d1e3d3-a645-4388-a217-4d88380802df",
    "siteId": "de4b0a91-5caa-4732-a530-67cfb2b0c42d"

If all you want is the url, use /sharepoint/site/webUrl.

Friday, March 10, 2017

Perhaps the only SharePoint Framework web part you will ever need

Ok, that’s not entirely true, but it might come in handy for sure…

[Update 2017-03-13]
This post sparked some action over the weekend on twitter and Facebook, and as a response Pat Miller at Microsoft put out one guidance article and one post with thoughts around the web part. The first one, How to block webparts from noscript sites, goes into detail how you today can mark a SPFx in a way so that you cannot add it to non-script sites (Group sites, Delve blog, sites where script is turned off etc.) Once this capability moves from the developer to the IT admin it's way better than any CAS policy we ever had back on-premises. The other is an issue titled General thoughts on a modern script editor webpart, which explains why Microsoft did not deliver this out of the box themselves.

Both of them are must-reads in my opinion to better understand how Microsoft think about governance in SPFx.

[Original post]
Unless you are all new to SharePoint pages, the chance that you have used at least one script editor web part or a content editor web part is pretty high. With the advent of the SharePoint Framework, Microsoft has given developers a way to create JavaScript solutions for modern pages. If you however have some small snippets or existing code, going the whole SPFx route might be a bit overkill.

Which is why I created a script editor web part for modern pages. Simply paste in any script or html, and it is rendered on the page.


Code can be found at the sample SPFx web part github repo from Microsoft. Also a big thank you to Waldek for always being helpful and helping me with how to load a script async in SPFx.

The code works by loading each <script src> in sequence, and then executing any other script block. So if you have script dependencies, simply list them in the right order and it should just work.

Thursday, March 9, 2017

My “don’t-do-it” modern page header configurator web part

In a current project we are making heavy use of the modern layout for lists, libraries and pages in Team Sites. I’m very much known for scoping things down, but the huuuge header of modern pages just takes up too much valuable screen estate the way it is. As I’m also know for not sticking to my principles, I went out and misused the SharePoint Framework and created a part which does CSS injection on the page to override the default behavior. My hope is that Microsoft gives us some default options regarding the header, so I can kill this code before it spreads.

To be clear – I do not recommend this approach, and rather accept how it is until proper support is added (but where’s the fun in that right?)

The Delve blog allows adding a header photo to posts and the home page of group team sites does not have this huuuge banner – clear evidence that Microsoft know how to implement it if they want to ;)

If interested, you can get the code from The code also has a nice sample on how to use a color picker as a property pane control.


Monday, March 6, 2017

Modern and it’s funky accent colors

I’m all about doing funky and random stuff, but the way accented colors are applied on modern pages in SharePoint Online has the distinct taste of fungi.

The colors scheme of the tenant has no bearing what so ever. It’s all calculated based on the site Title. If you however create a composed look and specify the accent colors, this will in fact overrule the random color.

A site named “a”


A site names “b”


I have not figured out the exact hashing formula to pick the color, but I have so far identified 10 colors in use – the same colors shown for sites listed on the SharePoint home page. From this list there’s a distinct tendency towards red – all very bright and alerting. How about a more calming color scheme?


If you don’t like any of these colors, or have a hard time finding a title to give you the right color, be sure to create and apply a composed look to your team or group site. Or go with old style pages where the randomness is no where to be seen – but where’s the fun in that?

Enable usage policy for Office 365 Groups using the AAD V2 PowerShell module

A quick note, at the time of this writing you have to use the preview commandlets as the released one is missing the settings commands needed.

First off you have to install the AAD Preview V2 PowerShell module.

Find-Module AzureADPreview #to ensure it's in the list when doing install
Install-Module AzureADPreview

Next up load the module into your PowerShell session and connect to Azure AD

Import-Module AzureADPreview
$credentials = Get-Credential
Connect-AzureAD -Credential $credentials

Once connected we get a copy of the template for Unified Groups, and use this to create and set new settings. If you already have settings in place for Group.Unified to for example disable group creation, you need to load and modify this setting object instead.

$policyTemplate = Get-AzureADDirectorySettingTemplate |? Id -eq 62375ab9-6b52-47ed-826b-58e47e0e304b
$setting = $policyTemplate.CreateDirectorySetting()
$setting["UsageGuidelinesUrl"] = ""
$setting["ClassificationList"] = "Low,Medium,High"
$setting["DefaultClassification] = "Low"
$policySetting = New-AzureADDirectorySetting -DirectorySetting $setting

You might have to wait a little bit before it’s all working, but once all set, if you edit a groups’ settings, you will see a dropdown for classification, and a hyperlink to usage guidelines.


The setting is also visible on the group site.


Wednesday, February 22, 2017

I’m late to the party again, but so the is the “Create site” UI

I want full control over sites and Office 365 group creation and I’ve seen the setting in SharePoint Online Admin for ages to specify my own form URL. My bad for not testing this earlier.


Well, turns out, this does not replace the default form, which still allows me to create an Office 365 group off the, but instead adds a tiny tiny link on that form which no one will ever click.


Seriously? Which leaves the only option left, hide the “Create site” link altogether, and tell users to go to my fab order form instead.

Tuesday, February 21, 2017

All you never wanted to know about Exchange Online, Azure AD and Office 365 Groups creation

Before setting the scenario, the solution to my problem would be either an Office 365 group with dynamic Azure Active Directory membership where all services in the Office 365 group where opt-in and not mandatory, or an e-mail enabled security group with dynamic membership. Neither of those options exist and we ended up having one dynamic distribution group and one dynamic security group.

Tuesday, February 14, 2017

Microsoft Flow, the lazy coder’s alternative to SharePoint web hooks

SharePoint web hooks has made it out from preview and into general availability, and is a great way for applications to act on changes to items in SharePoint. Think workflows where you want to run custom business logic when someone creates or edits an item. For the old-timers a web hook is just a new type of event receiver on the created/updated/deleted events.

The good thing about web hooks is that you can tack them on using either an Microsoft Azure Active Directory application or a SharePoint add-in, using application credentials. This of course is the proper way to do it, so if you are coder-proper, then stop reading now.

So why do it the lazy way using Microsoft Flow?

If you go the route of creating a web hook programmatically you have some plumbing to do up front:
  • Get an administrator to register your AAD app or SharePoint add-in
  • Write code to subscribe the web hook to events on the list/library
  • Write code to re-new the web hook subscription once it expires (max 6 months)
  • Write code to fetch the data of the item which triggered the event
The lazy approach is somewhat a smoother ride, and is what I used at a recent hackathon to get things working fast. The drawback is that Microsoft Flow runs in user context, so you only get events on items you or the account you used to authorize a particular connection have access to – but this might work our just fine for many scenarios. Using a service account is one possibility.

If all you want is access to the data of a created/modified item and want to pass it to a custom API, then using Microsoft Flow makes it very easy. One trigger action which return data for all item fields, and one HTTP action (with swagger if you fancy that) to your custom API with a payload of your choice and you’re set. You can focus purely on the API logic and let Microsoft Flow handle the eventing for you. If you want to handle both created and modified items you need to create two flows.


I'll be fair and say that Microsoft Flow currently does not handle everything and come with some caveats.
  • Currently no support for updating taxonomy field
  • Currently no support for updating lookup fields
  • Currently no support for updating choice fields
  • Currently no support for updating people fields
  • Updated items will have “you” or the account used in the connection to SharePoint as the last modified user
  • Updating a list with more than 12 lookup/taxonomy columns will report as failed, even though they work
As you can see, the weak points for now are on updating items, not getting the values of the item itself - so happy flowing!

Tuesday, February 7, 2017

How to consent to an Office 365 service app

At times you might want to create services which interact with the Microsoft Graph or Office 365 API’s.

If your application has an actual web page you will get prompted for consent when you visit and login. If you have elevated privileges you would tack on &prompt=admin_consent to the URL and then your service can authenticate and do what you need it to.

If you create an Office 365 application entry in Azure AD and have no web application tied to it, this is not automatic.

One approach to get the consent URL is to create a small c# app using the ADAL libraries.

string ResourceId = ""; // Microsoft Graph End-point
Uri RedirectUri = new Uri("[APP ID URI]");
ClientId = "[O365 App ClientId]";
ClientSecret = "[O365 App ClientSecret]";

var authenticationContext = new AuthenticationContext("");
var url = await authenticationContext.GetAuthorizationRequestUrlAsync(ResourceId, ClientId, RedirectUri, UserIdentifier.AnyUser, "prompt=admin_consent");

If you have a multi-tenant app, you have to login to each tenant using the outputted URL to consent per tenant.

Monday, February 6, 2017

Gaps and differences between a Group 365 Modern Team Site and a plain old Team Site

This post outlines some of the differences between an Office 365 Group Modern Team Site and a plain old SharePoint Team Site as of February 7th 2017.

[Updated to match the GA announcement February 23rd 2017]

The gaps may or may not affect you, but from a document management perspective we keep hitting several of the differences in every single projects which often leads to falling back to a plain old Team Site.

As there has been talks of enrolling/upgrading plain old Team Sites into a modern site in a group, I hope the limitations will go away and align more in the future. At Puzzlepart we see the most important ones being able to programmatically configure up pages in a scalable way and having access to synchronized content types.


Saturday, January 21, 2017

How to rename the Title field in a list/library using PnP templates

Took me some testing to get this right, but turned out not that hard. You add a reference to the Title field with the out-of-box id fa564e0f-0c70-4ab9-b863-0177e6ddd247, and then change the display name. In the sample below I’m also using a reference to a language resource as I need support for four languages.

<pnp:ListInstance Title="My List" TemplateType="100" Url="Lists/MyList">
        <Field ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Type="Text" Name="Title" StaticName="Title" DisplayName="{resource:MyList_MyTitle}" />

Thursday, January 19, 2017

Clarification on automatic managed properties in SharePoint Online

For some time now automatic managed properties in SPO are listed grayed out, with no settings shown. They sort of seem like ghost properties, not usable for anything. Fortunately this is not true.


Displaying no properties does not mean that they are not working as you would expect. The Microsoft SharePoint Escalation Services Team explained it all in a blog post dated August 30th 2016, but it’s not easy to understand. My take is that this was done in order to optimize schema handling in SPO, where there are millions of schemas. They were slowing up, but now at least you can still work with them.

Before you start mapping your crawled properties to new managed properties, see if the automatic ones work as you would expect. The default settings for an automatic managed property (has OWS in the name) are:
  • Queryable
  • Retrievable
  • Multi-value (taxonomy and multi-user fields only)
  • Searchable (taxonomy fields only)
If not, use my rule of 3 below.

Mikaels managed property rule of 3:
  1. Use automatic managed properties if possible
  2. Map crawled properties (the plain ows_columnname ones) to the RefinableXXYY re-usable properties if possible. And do give them an alias for easier management and use
  3. Create a custom managed property as last resort – which is only possible for Text and Yes/No fields.
Shout-out to Joanne Klein for making me blog something which I have just taken for granted :) and to Tarjei for verifying the settings of the auto generated managed properties in an on-prem environment for me. And to Marc Anderson for being the glue!

Friday, January 6, 2017

Retrieving search results from private Groups in Office 365 via REST

By default when you run a search REST query against SharePoint Online results from private Office 365 Groups are not included.

By adding &Properties=’EnableDynamicGroups:true’ to the URL, you will also get results from private groups.

If you are running REST POST requests, add the following to your JSON payload (odata=verbose):


When using CSOM, it seems dynamic groups are included by default.