Microsoft SharePoint Conference 2019

Another year, another conference! Microsoft and SharePoint has evolved immensely in the past 20 years. For those of us that have been around that long (inside and outside Microsoft, and those that were outside and are now inside), watching it grow with the industry and web technologies has been exciting and at times maybe not so much.

Probably the most interesting thing to watch has been seeing the community evolve. Just like the stock market, it comes and goes in cycles. Newbies come in, experts go out. Some strike it rich, others not so much. Entire ecosystems were built from SharePoint; companies were created, companies died.

So where do we reside today? From someone that has been around a while (yeah, there are a few left standing that have been around much longer), I see a new cycle starting. Lots of fresh newbies have arrived with energy and fresh ideas (well kinda, its hard to not think of something that someone hasn’t tried, but nice to watch someone attempt it again even if it may not go anywhere). I have always promoted finding super smart new speakers to fill the conference pool and now I find myself working for Solliance which has been a long time conference participant in conferences like DevIntersection, Azure AI, AngleBrackets and a few others. As part of that my voice is a bit bigger given all the time and energy I contribute (yes, I do most of this work for free as part of my contributing back to the community).

Running a conference is a lot of work. More than you could imagine. SharePoint Saturday’s are one thing, a full blown conference with 5000+ attendees and demanding speakers and conference owner(s) can drive any person a bit crazy at times (next time you see Lyman, you should buy him a a nice stiff drink).

This year has been a bit different from the logistics side as we have moved to the new Hubb platform for speaker and session management. This presents some interesting challenges as we have to sync the data from the Hubb to the Solliance backend. As a PowerShell master, I was able to take from the many millions lines of PowerShell I have laying around and easily build a sync layer (multi layers of auth, two different web technologies). This layer works great as a point to point sync, but as you start to add new rules and requirements such as:

  • Only speakers that have accepted and signed
  • Session must be approved
  • Only community ones should be published
  • Titles change with no static session codes
  • etc etc etc

As you can imagine and may have noticed once or twice, not a simple or well oiled machine starting out. However, things have converged and its working well now. Unfortunately, the back-end needed some work as we were not utilizing the awesome new “slot” technology of Azure Web Apps nor were we fully utilizing the CD/CI of AzureDev ops. And let’s just say there wasn’t really a naming convention implemented so managing the Azure resources was a real pain in the a$$. That has since been resolved and all of the Git repos are tied to build and release in AzureDev ops that then push to our staging slots. From there our release manager can then switch the production and stage slots for instant deployment. I am thoroughly enjoying not having to manage any of this now…automation is beautiful.

In addition to all the above, I have been busy running through security and testing of our GDPR\AB375\PIPEDA platform (which is the topic of my SPC19 session). Building a platform makes you realize just how much people don’t know about GDPR technical implementations. It is by far the best content I have ever produced and I guarantee you will learn things that the EU or CA lawyers never would be able to tell you.

Looking forward to seeing you at SPC19 in May! Register here for $50 off registration.

Content Type Document Template – The right way.

Here is the code to set the document template for a Content Type such that when adding it the “Content Type” field in the library will be set properly.  Notice how you have to get the XmlSchema property for the _cts folder name (the content type name now, may not be the name later).
function SetDocumentTemplate($ctName, $filePath)
{
$fi = new-object system.io.fileinfo($filePath);
if (!$fi.exists)
{
return;
}
$contentTypes = $context.Site.RootWeb.ContentTypes
$context.Load($contentTypes)
try{
$context.executeQuery()
write-host "Getting Content Types - done." -ForegroundColor Green
}
catch{
write-host "Error While Fetching content types $($_.Exception.Message)" -foregroundcolor red
}
$contentType = $contentTypes | Where {$_.Name -eq $ctname}
$context.Load($contentType)
try{
$context.executeQuery()
write-host "Getting Content Type - done." -ForegroundColor Green
}
catch{
write-host "Error While Fetching $($ctName) content type $($_.Exception.Message)" -foregroundcolor red
}
[xml]$data = $contenttype.SchemaXml;
$folder = $context.Site.RootWeb.GetFolderByServerRelativeUrl("$($data.ContentType.Folder.Attributes["TargetName"].Value)");
#$folder = $context.Site.RootWeb.GetFolderByServerRelativeUrl("Document Templates")
#$ctsfolder = $context.Site.RootWeb.GetFolderByServerRelativeUrl("_cts");
#$subfolders = $ctsFolder.Folders;
$context.Load($folder)
#$context.Load($ctsfolder)
#$context.Load($subfolders)
try{
$context.executeQuery()
write-host "Loading folder done." -ForegroundColor Green
}
catch{
write-host "Error While Getting $($ctname) content type information $($_.Exception.Message)" -foregroundcolor red
}
<#
$enum = $subFolders.GetEnumerator();
while($enum.MoveNext())
{
write-host $enum.Current.ServerRelativeUrl;
}
#>
$templateName = $folder.ServerRelativeUrl + "/" + $fi.Name;
write-host "Uploading $($templateName) document template... " -NoNewline
$FileStream = New-Object IO.FileStream($filePath,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $fi.Name;
$Upload = $folder.Files.Add($FileCreationInfo)
$contentType = $contentTypes | Where {$_.Name -eq $ctname}
$context.Load($contentType)
try{
$context.executeQuery()
write-host " done." -ForegroundColor Green
}
catch{
write-host "Error While Uploading $($templateName) document template $($_.Exception.Message)" -foregroundcolor red
}
write-host "Setting $($ctname) content type document template... " -NoNewline
$contentType.DocumentTemplate = $fi.Name;
$contentType.Update($true)
try{
$context.executeQuery()
write-host " done." -ForegroundColor Green
}
catch{
write-host "Error While Setting $($ctname) content type document template $($_.Exception.Message)" -foregroundcolor red
}
}