The blog of Wictor Wilén

  • SharePoint Framework: how to properly dynamically populate dropdown property pane fields

    Tags: SharePoint Framework

    One of the key parts of SharePoint Web Parts is the ability to have them configurable using the Web Part properties. This story is still true with client-side Web Parts in the new SharePoint Framework. In this post I will show you one of the more common scenarios; how to populate drop downs (and other fields) in the property pane dynamically. But also show you how what's wrong with the current implementation.

    Client-side Web Part Property Pane basics

    The Property Pane in client-side Web Parts are defined by the propertyPaneSettings method. It's a method that returns an IPropertyPaneSettings object representing the pages, groups and fields. This method is invoked whenever you click to edit the Web Part. The method is "synchronous" meaning that you should return a static set of pages, groups and fields - there's no option to wait for it to load (SPFx issue #127).

    Defining the Dropdown

    For a Dropdown we use the PropertyPaneDropdown field and specify for instance it like this, in the propertyPaneSettings method.

    PropertyPaneDropdown('listName', {
      label: strings.DescriptionFieldLabel,
      options: this._options

    In this case the options property references a local variable defined as below:

    private _options: IPropertyPaneDropdownOption[];

    Loading the data…

    But when do we load this data into the local variable. We do have a couple of options to do this, but there really is only one viable option at the moment and that is to use the onInit<T>() method. This method always runs when the Web Part is loaded or is added to a page, and it only runs once and it is the only option we have if we want to load something using a promise and make sure to have it loaded before we have the chance of rendering the property pane. The onInit method returns a Promise and that allows us to actually block the loading of the Web Part until we have the data.

    To load data, mock or live, I've created a simple list data provider, that you can find in the following Gist. Pay attention to the fact that I have set a delay on the mock loading to 5 seconds, this is to simulate a slow request and show you how bad this current implementation actually is.

    Then I implement the onInit method as follows:

    public onInit<T>(): Promise<T> {
      let dataService = (this.context.environment.type === EnvironmentType.Test || this.context.environment.type === EnvironmentType.Local) ?
        new MockListsService() :
        new ListsService(this.context);
      this._options = [];
      return new Promise<T>((resolve: (args: T) => void, reject: (error: Error) => void) => {
        dataService.getListNames().then(lists => lists.forEach(list => {
            text: list,
            key: list

    First of all I create my data service object (mock or real one). Then I create a new Promise that uses my list service and once the list data is read it populates the local variable holding the data for our dropdown and finally I resolve the promise.

    There are some articles and Github repos that uses another approach, they just return a resolved promise and let the call to the external data service run in the background. If that background request takes to long time (the simulated 5 seconds for instance) or fails then the user might have time to open the property pane and see an empty dropdown.

    Now when the web part is added to a page or a page a loaded with that web part the onInit method will "block" the web part from rendering until it has the data for the property pane. Well, that's not good, but that's how it is at the moment. There is however a possibility that we might be able to use displayMode property of the web part and only do this when we are in edit mode. I have not been able to verify this as the workbench always are in edit mode and none of my tenants actually loads the client side web parts in the modern pages - I'll get back on this.

    Another annoying thing is that since this is blocking the rendering, not even showing a spinning wheel or something, the user experience is quite bad if you have long running calls since nothing is shown (SPFx issue #228).


    I've now shown you how to pre-load data for your property pane fields, yes same approach works for other field types than dropdowns as well. But is this the proper way then? Nope, it isn't but I have great hopes that this will be fixed in a better manner (see linked issues). If not we still have the option of creating completely custom property pane fields that allows us to do basically whatever we want.

  • SharePoint Online CDN features announced in preview

    Tags: SharePoint Online

    Today, Mr Vesa, announced the availability of the (long awaited) CDN features for SharePoint Online. The SharePoint Online CDN features allows you to turn one or more libraries in your SharePoint tenant into a repository for assets that you want to store in a CDN for performance reasons and geo-distribution reasons.

    SPO Public CDN

    How to set things up

    I'm not going to rehash everything that is outlined in the announcement post, but rather highlight a few important things.

    To get started and turn one of your libraries into a CDN enabled library you need to install the latest SharePoint Online PowerShell cmdlets to get access to some new and updated PowerShell cmdlets. Once you have that all you need to do is first enable it on your tenant and then add libraries for cdnization:

    $creds = Get-Credential
    Connect-SPOService -Url -Credential $creds
    Set-SPOTenant -PublicCdnEnabled $true

    Once this is done then you choose what libraries to use as the source for your CDN. You can point directly to a library or a subfolder in a library.

    New-SPOPublicCdnOrigin -Url

    When you do this you get a big and yellow warning stating that everything you add in this folder from now on will be pushed to the CDN, and that CDN is publicly available and not governed by all the nice policies we have in Office 365. So, don't put your annual report drafts in there!

    Note, it might take a few minutes until it is all ready for usage after adding or changing the origins. 15-20 minutes is not uncommon.

    You can always retrieve all your CDN origins by using the following command:


    This command will list the ID of each CDN origin as well as the origin. The ID is very important, because you need that when you construct the URL to the CDN. It's probably one or more Guids in that ID…

    How to access the files in the CDN

    To get access to the files in the CDN you need to construct a path using the ID for the CDN origin like this:

    For instance

    Yes, it's a bit long but that's how it is.

    If you now try to access an image or script in this CDN by just typing the URL in the browser, you will get an error stating "Invalid referer". This is by design and you need to add a HTTP Header to see the image/script, the Referer header with the value of the URL of your tenant (see announcement blog). In cases where you embed the image in a page or load the script from a page, this is done automatically for you by the browser. An even easier way is to just create a page and insert a Picture from Address, and paste your CDN Url.


    There's a couple of caveats to the CDN as of now. One thing I had hoped was that you could use image renditions in combination with this, which would have been AWESOME. Nope, you can't. Vesa, can you add that to the todo list?

    [Update 2016-09-29] The image renditions are partly supported, you can now use width, height and cropMode (fit for instance) as query string parameters for the image. But not RenditionId - once that can be done this feature is rock solid!

    [Update 2016-09-29] CORS support has been enabled! Thanks you to the product group for fast and quick turnaround for these kind of features!

    Another quite important thing is that the CDN isn't CORS enabled. They do a check for the referer, see above, so that the request are coming from the correct tenant. But if you try to use jQuery or some other mechanism to load scripts or assets from the CDN location you get

    No 'Access-Control-Allow-Origin' header is present on the 
    requested resource. Origin '' is
    therefore not allowed access.
    The response had HTTP status code 406.

    I wish they added the possibility to allow CORS requests from the tenant, just as they only allow request refering from the tenant.


    I think this feature is awesome and I have already upgraded a few tenants and customers to use this new feature for some embedded resources. Oh, did I say this is free of charge and a part of your Office 365 subscription. Free beer is good beer, despite in preview!

  • SharePoint Framework Nuggets: working with GUIDs

    Tags: SharePoint Framework

    SharePoint developers - we do like GUIDs, don't we. We all read RFC4122 both once and twice. And now with SharePoint Framework and the goal to embrace all them Macintosh and open source people - they gotta have their fair share of GUIDs.

    And to aid with that the SharePoint Framework got some really nice GUID features, although a bit unpolished as you might notice - but this is all preview bits at the time of writing.

    SharePoint Framework Nuggets - GUIDs

    The Guid class

    First of all we must have the option to create GUIDs. There might be a situation that you need to store something really, really unique - to help with the we do have the Guid class in the @microsoft/client-sp-base module. This class both allows you to create new Guids, parse Guids and validate Guids.

    This is how you import the Guid class:

    import { Guid } from '@microsoft/sp-client-base';

    Then to create a Guid, you use the code below. The newGuid method can take an optional parameter if you need to create a custom random generator. By default it generates a version 4 UUID, also known as a pseudo random UUID, which can be generated in a browser. I suggest you skip passing in custom random generators.

    var guid: Guid = Guid.newGuid();

    What if someone gives a "GUID" to you, can you trust it is a proper Guid, no you can't you need to validate it. That can be done using the isValid method, which takes a string as in input.

    if( Guid.isValid(' f0a1f189-dae4-49f5-8846-3a17429fd52') ) { alert('Valid') };

    Then we finally also have a method to parse a string potentially containing a Guid, tryParse. The method will either return a Guid object or undefined.

    var guid: Guid = Guid.tryParse('f0a1f189-dae4-49f5-8846-3a17429fd52');

    The GuidHelpers class (@internal)

    [Update 2016-09-20] - The GuidHelpers class is marked internal and will be removed in future builds of the SharePoint Framework.

    There's also another class in SharePoint Framework for Guids, the GuidHelpers class. This class lives in the @microsoft/sp-client-preview module. It has a set of similar function to generate and validate Guids, but it does not work with Guid objects, it uses strings instead. For instance the GuidHelpers.generateGuid() returns a string. Another issue is that the GuidHelpers.isValid() does not validate Guids the same way as the Guid.isValid does (issue #201 in the SPFx Repo).

    GUID validation issues

    At the moment (drop 3 of SPFx) I would stay away from the GuidHelpers class.

    As usual there's some code samples of this to be found in this Github repo:

    Happy GUIDing!

  • SharePoint Framework Nuggets: logging like a pro

    Tags: SharePoint Framework, SharePoint

    I guess that almost every application or solution you ever built has contained some portions of a logging mechanism. And how many of you have written your own - yup, all of you! But what about the SharePoint Framework - yes, it has built-in logging!

    SharePoint Framework Nuggets - logging like a pro

    How to log in the SharePoint Framework

    Logging is a very convenient and easy way to keep track of events happening, instead of having breakpoints, or in JavaScript even worse - alerts. The SharePoint Framework (SPFx) has as all decent frameworks a built-in logging mechanism, albeit very simple, but still yet valuable. It's contained in the @microsoft/sp-client-base module and the class is called Log. To use it in your SharePoint Framework solutions you need to import it as follows:

    import {
    } from '@microsoft/sp-client-base';

    The Log class contains four static methods for logging:

    • info
    • warn
    • error
    • verbose

    The names are exactly what you expect, the info is used for information, warn for warnings, error for errors and verbose for when you just have to much on your mind and want to spit it out.

    In the SharePoint Framework implementation all logging is done to the JavaScript console and you can see the logging using the developer tools of your favorite browser. It can take some searching to find them as SPFx spits out quite a lot of logging by itself.

    All static methods have the same signature, except the error method - they take three arguments:

    • source: the source of the logging information (max 20 characters), such as method or class name
    • message: the actual message to log (max 100 characters)
    • scope: an optional service scope (more on this one later)

    The error method takes an Error object instead of the message string, otherwise they are the same.

    This is how it could be used in client side web part:

    public render(): void {
      this.context.statusRenderer.displayLoadingIndicator(this.domElement, strings.Loading);
      Log.verbose('SpFxNuggets', 'Invoking render');
      this._webInfoProvider.getWebInfo().then((webInfo: IWebInfo) => {
        if ( {
          throw new Error('Mayday');
        }'SpFxNuggets', 'Service OK', this.context.serviceScope);
        this.context.domElement.innerHTML = `<h1>${webInfo.title}</h1>`;
      }).catch((err) => {
        Log.error('SpFxNuggets', err);
        this.context.statusRenderer.renderError(this.domElement, err);

    In the example above I use the verbose method to log that we're in the render method. Just verbose information. I also added logging to when the service returns (the promise is fulfilled) to log information that it has returned. In that info method I use the service scope of the web part, and when using the service scope, it replaces my source with the real name (JavaScript name) of the web part. Finally I log the error in the catch method. The image below shows the console output.

    Console output

    As usual you can find all the source code in this repository:

    Happy logging!

  • SharePoint Framework Nuggets: render error messages

    Tags: SharePoint Framework, SharePoint

    Do you write code that potentially can throw an error or an exception? Oh, you don't - but sure you use a web service or external service or something that can throw an error. Well, it is you responsibility to handle the error and make sure to inform the user in a good way that something bad happened. With that I mean, do not show just a Guid.

    With the SharePoint Framework being all client side I think it is important to have control of your client side Web Parts and make sure that you properly handle and display error messages in a consistent way. In this short post I will not go in to the JavaScript error handling details, but rather show you another nugget in the SharePoint Framework that helps you render error messages in a standardized and consistent way.

    SharePoint Framework Nuggets - Render error messages

    Render Error messages

    Just as in the last post on the loading indicator the SharePoint Framework actually has built-in functions for rendering messages in SharePointy way. In the same class (and interface) as we had the loading indicator functions we also have two methods for managing error messages, found in the context of the current client side Web Part.

    • renderError(domElement: HTMLElement, error: Error | string): void;
    • clearError(domElement: HTMLElement): void;

    The renderError  method is used to display an error message in an HTML element. It has one parameter for the error message, which can either be a string or an Error object. And the clearError removes any rendered errors in the specified DOM element.

    Here's an example on how we could use it:

    public render(): void {
      this.context.statusRenderer.displayLoadingIndicator(this.domElement, strings.Loading);
      this._webInfoProvider.getWebInfo().then((webInfo: IWebInfo) => {
        if( {
          throw new Error('Mayday');
        this.context.domElement.innerHTML = `<h1>${webInfo.title}</h1>`;
      }).catch( (err) => {
        this.context.statusRenderer.renderError(this.domElement, err);

    It's the same render method that was in the loading indicator demo but with the difference that we have added the clearError method at the beginning of the render method (once again a redundant operation since the displayLoadingIndicator will override anything inside the DOM element, but you get the point). Then I introduced a property on the Web Part that when set it will throw an error and in our catch method we use the renderError method to render the error, as shown below.


    Fully working code can be found at this repo:

    If you carefully explored the latest drops of the SharePoint Framework (yes, this is all still beta and bits and pieces are moving around) you might notice that the BaseClientSideWebPart contains direct access to these methods (clearError and renderError). The clearError is just calling out to the statusRenderer while the renderError method first clears the loading indicator, as I do manually above, then renders the error and finally also logs the error.

    Good luck!

  • SharePoint Framework nuggets: the loading indicator

    Tags: SharePoint Framework, SharePoint

    SharePoint Framework is all about rendering stuff on the client side, avoiding the long overdue ASP.NET Web Forms technology that SharePoint (Online) is still fundamentally based on. When rendering things client side everything is done asynchronously, to avoid locking down the UI threads and having a user experience that is fluent.

    In order to give the user good feedback that things are happening in the background, you need to have some kind of visual cue that tells the user - hey I'm doing stuff now, gimme a minute. There are thousands of different ways to do this and everyone does it differently; ranging from animated gifs to "loading" texts. And everyone using different methods does not always help with the user experience - so why don't we have a common way to do this?

    We actually do have this built into the SharePoint Framework!

    SharePoint Framework Nuggets - The Loading Indicator

    The SharePoint Framework Loading Indicator

    The SharePoint Framework contains a set of nifty methods that we can use to show a loading indicator in standardized and common way.

    The SharePoint Framework contains a special interface and corresponding implementation that is called IClientSideWebPartStatusRenderer. This interface defines two methods:

    • displayLoadingIndicator(domElement: Element, loadingMessage: string): void;
    • clearLoadingIndicator(domElement: Element): void;

    The first one, displayLoadingIndicator, is used to create a loading indicator with a spinning wheel and a loading text and then replace the inner contents of a HTML element with that code. For instance, for client-side Web Parts that is loading data dynamically should use this as one of the first things in the render() method. The second one, clearLoadingIndicator, does the opposite, it removes the loading indicator.

    The IClientSideWebPartStatusRenderer is always accessible through the IWebPartContext, that is on the context object of your Web Part.

    Here's an example on how to use it:

    public render(): void {
      this.context.statusRenderer.displayLoadingIndicator(this.domElement, strings.Loading);
      this._webInfoProvider.getWebInfo().then((webInfo: IWebInfo) => {
        this.context.domElement.innerHTML = `<h1>${webInfo.title}</h1>`;

    As you can see the first things we do is to replace the whole client side Web Part with the loading indicator and a loading message. Then once our Web Part is done and have data to render, we clear out the loading indicator before rendering our stuff. In this case it is a redundant operation to clear the loading indicator, since we are replacing the whole Web Part HTML with our custom rendering. If we had a more advanced user interface we could put the loading indicator in another of our elements and then remove it.

    And this would be how it looks like in the SharePoint Workbench, when loading for 2 seconds.


    You can get a copy of all the code at this Github repository:

    Happy Web parting!

  • Conference season, fall 2016, and where I'll be

    Tags: Presentations, SharePoint Framework

    Summer is over, slacking time is over, it's time to get up to speed and learn some new stuff. There's very much to talk about this fall if you're interested in SharePoint. And this fall I will do a couple of conferences as a speaker, which I very much looking forward to.

    TechDays 2016, Amsterdam

    For the first time I will attend and present at the TechDays 2016 in Amsterdam, the 4th and 5th of October. A local conference hosted by Microsoft. I will present three sessions:

    • Introducing the SharePoint Framework
    • Deep dive building client-side Web Parts using SharePoint Framework
    • SharePoint Futures - Christmas came early this year!


    The SharePoint and Office 365 track will be outstanding with where you also can listen to Waldek Mastykarz and Albert-Jan Schot.

    SharePoint and Exchange Forum, now SEF Unity Connect

    I don't know for how many years I've done this show, SEForum, 26th to 28th of October. It's the best conference for SharePoint, Office 365 and Exchange in Sweden, the Nordics, Scandinavia. And you'll find all the experts here, such as Spencer Harbar, Eric Schupps, Jesper Ståhle just to mention a few. This year I'm honored to do the keynote, together with Dan Holme (Microsoft). It will be a blast! And I will also do the following break-outs:

    • Building Modern Solutions with the SharePoint Framework
    • SharePoint as an Intranet


    If you're planning to attend, please use this code SEFWICW10 to get 10% off!


    If you're around, come by and say hi, looking forward to meeting you all out there on the road.

  • The SharePoint Framework (SPFx) is here!

    Tags: SharePoint, SharePoint 2016, SharePoint Online, SharePoint Framework

    Today is the day many of us have been waiting for since the big SharePoint event at May the 4th. The highly anticipated SharePoint Framework (SPFx) is here and announced in at the SharePointFest, in this blog post, as well as in the new Github repo for SharePoint. Personally I've been waiting for this even longer after being involved by the product team to give early feedback and also attending the first top secret DevKitchen "hackathons" where we could try out very early bits.

    That feeling when you use the SharePoint Framework the first time...

    The first release of many to come…

    This is the initial public preview release, officially christened the SharePoint Framework Developer Preview, is a beta, maybe an alpha, of the SharePoint Framework. This is by no means something you should use or deploy to production. Things will change! Period. There are several known issues at the moment and some of them will likely incur breaking changes. But please, build stuff and give feedback to the product team, use the Issues feature in the Github repo.

    This initial release focuses on client-side Web Parts which can, once released, be used in you classic SharePoint sites and pages as well as in the new modern user experience that is slowly being rolled out throughout the suite. As some of you know, I've spent quite some time on Web Parts and written a book on the topic, so this is something that gets me really excited.

    How and where to get it!

    All you need to do to get your hands on it is to follow the instructions on the Github repo. I'm sure we'll see tens and hundreds of blog posts on how to do it, but I recommend you to follow the one in the repo to start with. And, if you can't follow it, create an issue, make a pull request with an update - make sure we get good official documentation! Heck, I'm pretty sure I will write a couple of posts on the topic, but I will also continue to provide feedback on the framework and the documentation.

    You will find samples, documentation and all you need in a set of brand new repositories in Github, also under a brand user/organization called…SharePoint (yes, no more generic Office dev, SharePoint is back!).

    Need to know more?

    Keep the conversation going on Twitter, SharePoint Stack Overflow, the new Office 365 Community network and other social media, and do use the #SPFx hashtag. I'll try to hang around at the SharePoint Stack Overflow as much as possible, since that is the best platform of the above mentioned ones.

    I've previously written a Q&A on SharePoint Framework and will continue to update that post with details and changes in the current preview release.

    Now, go, build something awesome!

  • Why my Pages, with a custom Page Layout, was not indexed in SharePoint Online!

    Tags: SharePoint Online, SharePoint 2016

    Here's one of these real life stories that caused some headache for quite some time but was in the end very easy to resolve. I'll write it down and hopefully some of the search engines pick it up and help some other poor soul out there.


    We have a solution that uses publishing pages to manage news articles and information pages in SharePoint Online. These articles and pages have a custom page layout with a custom content type, so they look decent and have proper metadata. They are all deployed using the PnP PowerShell cmdlets.

    Creation of pages worked flawless and the rendered nicely. They page layouts use jQuery, some Office Fabric components (including those nasty jQuery scripts for that).

    So far so good!

    The Problem

    We wanted to roll up this News articles through a custom Web Part based on a search criteria, and also show some of that metadata, such as News category, rollup image and more. But the pages was not indexed. First thought was that well, indexing in SharePoint Online usually takes everything from a couple of minutes to a couple of days, so just wait. Then summer vacation came - I'm not complaining - and when i got back we had index. Ok, good. But then I started adding some custom managed properties to the rollup feature and was waiting for it to pick up the changes. I clicked re-index the libraries, I clicked re-index the site, added new pages and articles, I might even sacrificed the cutest little kitten you can imagine - but nothing. The pages and articles was just not picked up by the crawler. So I started to smell something fishy.

    Is there something wrong with my SPO tenant? No, same issue across multiple tenants!
    Can it be the page layout? No, it renders perfectly in all browsers!
    Can it be the PnP PowerShell cmdlets? No, the same issue if I uploaded page layouts manually!

    Old man yells at cloud


    First of all I added the CrawlTime managed property to see when stuff was actually crawled and that there was nothing wrong with the crawler. I could see how this managed property was populated on other stuff than the pages. So there is obviously something wrong with our pages and not SPO.

    Time to get my troubleshooting gloves on and I brought out my checklist for this. Since I can't check trace logs (ULS) in SharePoint Online all I could do was to inspect the crawl logs. And now I could see in plan text that my news articles could not be crawled:

    "Item Error",
    "The SharePoint item being crawled returned an error when attempting to download the item.
      ( SearchID = F2A4A5E4-AAAA-AAAA-B034-10C593EF6CCE )",
    "8/4/2016 7:07 AM",

    So, the crawler can obviously not download my page! I also noticed the following cryptic error message on the site and library levels:

    "Container Error",
    "The SharePoint item being crawled returned an error when attempting to download the item. 
      ( Unknown Error The surrogate pair (0xD8DA, 0x272) is invalid. 
      A high surrogate character (0xD800 - 0xDBFF) must always be paired with a low surrogate 
      character (0xDC00 - 0xDFFF).; SearchID = 00D32C87-7CD9-4350-AFF4-BBF38B8EB712 )",

    Hmm, some Unicode errors?

    I was out of options and I could not do an IISRESET (Rule #3) - so I called a friend (Rule #4), Doc Hodgkinson. He was almost as clueless as I but asked my to test it on a normal SharePoint 2016 on-premises installation (born in the cloud you know) and see if I could replicate the issue and also then have the option to check for more detailed crawl and trace logs.

    And so I did. I ran the installer on a clean SharePoint 2016 install, started creating a page using our custom page layout and BOOM! The browser just went white!!! Nothing! It rendered fine in SharePoint Online (cloud-born innovation!)

    The solution

    Quickly I opened up the trace logs and reloaded the page and found this in the logs:

    SharePoint Foundation	General	ahi1s	Medium	
    Cannot find requested file: 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\Template\layouts/'
    SharePoint Foundation	Upgrade	aq775	Unexpected	
    CannotMakeBrowserCacheSafeLayoutsUrl ArgumentException: 15/0/1033/

    Aha! The Page Layout contains a ScriptLink control that points to that CDN location.


    I quickly changed it to a normal script tag and the page rendered fine in the SharePoint 2016 on-premises instance, and I uploaded it to SharePoint Online where it also rendered fine. And…after just a few minutes all my articles was indexed and queryable and I had my Managed Properties. And all was good!


    I find this bug very interesting, SharePoint Online obviously accepts full URLs in the ScriptLink property when rendered through a browser but when the crawler sees it something weird happens (also, I wonder why it gets Unicode errors on the site and library as well). Also, the code for ScriptLink is different for SharePoint Online and SharePoint On-Premises (I have NOT tested all CU's though). Also, it's really weird that it some time during the summer actually indexed the pages.

    All in all, actually using an on-premises installation for troubleshooting my SharePoint Online issues was a great idea (big thanks as always Neil) and I'll keep that option as a part of my normal routine from now on.

  • When a GUID is not really unique - I'm looking at you SharePoint!

    Tags: SharePoint 2016, SharePoint Online

    I have long thought that GUIDS are unique, well GUID actually stands for Globally Unique Identifier. And SharePoint is one unique product using GUIDS everywhere. There are 2^128 possible GUIDs to choose from, so there should be no need to reuse GUIDs as long as I'm alive methinks.

    Not even Chuck Norris is allowed to reuse GUIDsSharePoint uses GUIDs to uniquely identify Site Collections and Sites, and more, and this is for instance exposed through the ID property of the SPSite and SPWeb objects. If you take a look at the documentation for SPWeb.ID it actually says: "The globally unique identifier for the website" - which I interpret as this ID is unique, globally! Period.

    When you create a Site Collection in SharePoint you create a new Site Collection (SPSite) and a Root Web (SPWeb). The SPSite will be given a unique identifier, a GUID, and so is the root web as well. Due to the way the API is created you cannot find a web directly using the unique Web Id, you actually need the Site Id. Even so there are multiple applications and services that has only stored the unique Web Id and used that as something unique.

    Given (recent) changes and a new feature called Fast Site Collection Creation, used in SharePoint Online and to some extent in SharePoint 2016, this is no longer true and you can no longer trust in the Web Id being unique. When a site collection is created with a root web, specifically the SharePoint Team Site (STS#0), it is copied from a site master. The Site Collection is given a new GUID, but the GUID for the root web is copied from the site master. So, in SharePoint Online all your Site Collections with a root site of type Team Site will have the same id.

    There is no workaround for this, you cannot change the Id - your only chance is to use a combination of Site Collection Id and the Web Id. That is a dual GUID combo - can't be more unique than that.

    Some of you perhaps already knew this, some not. Hopefully you'll be aware of it now and I wish this would be different and that the Fast Site Collection Creation actually updated the Site identifier property, and since I most likely cannot have that I wish the documentation would be updated with a hint on this.

About Wictor...

Wictor Wilén is the Nordic Digital Workplace Lead working at Avanade. Wictor has achieved the Microsoft Certified Architect (MCA) - SharePoint 2010, Microsoft Certified Solutions Master (MCSM) - SharePoint  and Microsoft Certified Master (MCM) - SharePoint 2010 certifications. He has also been awarded Microsoft Most Valuable Professional (MVP) for seven consecutive years.

And a word from our sponsors...