Thursday, May 11, 2017

Using the Workflow Definition Language in Microsoft Flow

I’ve been playing with Microsoft PowerApps and Microsoft Flow since the first time it was introduced. And I must admit, I really love the way you can create mobile apps and flows in just a couple of minutes. I agree, once you really get in there, you bump into things that are still missing. But hey, that just means there is still room for improvement …

What I would like to show in this blog post is how you can extend your flows with a bit more advanced behavior by using the Workflow Definition Language. Actually, Microsoft Flow and Azure Logic Apps have a lot in common. Logic Apps allows you to use the Workflow Definition Language, containing a bunch of functions to give you logical behavior, functionality, parsing, conversion, … . The fact is that you can also use that Workflow Definition Language in Microsoft Flow, but it is not documented that well. Ohw, before I forget, the Workflow Definition Language from Logic Apps is described right here. Make sure you dig into that documentation to understand the functions you have at your disposition.

To illustrate how one can use it, I created a flow that will, starting from the PowerApp blog RSS create an email containing the new blog posts. Sounds like a simple one, but you need the Workflow Definition Language in order to make it a bit more fancy…

Starting with the trigger

I’ve decided to go for a trigger that runs every day, so that I can fetch the most recent blog posts every day. The setup looks as follows, still quite simple:

image

Filtering out only the “new” ones

I’m only interested in the “new” posts. Since my flow runs on a daily basis, I’m only interested in the posts that are less than a day old. Now the RSS feed items contain a field that contains the Published Date, so I want to filter on this field. In Flow, you can use the action Filter array from Data Operations to filter a collection of items. This will give you a “Simple” condition you can configure, but there is no way you can configure there: “Has to be published in the last 24 hours”. So you switch to “Advanced”, and now it’s up to the Workflow Definition Language to kick in.

image

The formula

@greater(item()?['publishDate'], adddays(utcnow(),-1))

checks whether the PublishedDate is greater than right now minus 1 day, giving you the posts created in the last 24 hours.

Preparing the HTML per blog post

Now that I have the most recent blog posts, I can start preparing them. I mean, at the end I want to send an email containing HTML to my email address. So for every item I want to create an <li> item containing an <a> anchor tag. So I want to do an Apply to each and then Concatenate some fields and text together. You can use the Compose action from the Data Operations for this.

 image

Make sure the formula is SURROUNDED WITH DOUBLE QUOTES or it will not work… The UI trims off the double quotes after save.

"@concat('<li><a href=\"', first(item()?['links']), '\">', item()?['title'], ' </a>')"

 

Only send an email if any blog post was found

This step could actually be put after the List RSS Items, but I’ve put it after the Apply to each. You can use the following:

image

Creating the email body

In the previous steps we already created the HTML for every item in the feed, now we just need to merge those items and surround it with some other HTML, just to make it a bit prettier. We can achieve this with another Compose action.

image

Again, make sure this formula is surrounded with double quotes or it will not work.

"@concat('<h1>New posts on the PowerApps blog</h1><ul>', join(outputs('Compose'),''), '</ul>')"

 

Sending the email

What remains is to send the email. Nothing more then passing on the output of the previous step as the email body. Since we constructed HTML as the body, the email can be sent as HTML too.

image

Run the flow, and there is the email:

image

Tuesday, May 9, 2017

Using Cross-Site Collection Publishing in SharePoint 2016

In this blog post I will discuss what you need to do to get cross-site collection publishing to work in SharePoint 2016. The Cross-Site Collection Publishing feature was introduced in SharePoint Server 2013 and allows you to use one or more authoring site collections to author and store content, and one or more publishing site collections to control the design of the site and to show the content. The authoring site collection contains so-called catalogs, which are lists that contain content, tagged with metadata (by means of site columns). These catalogs are indexed by the search system and made available to the publishing site collection. The publishing site collection issues queries for data that has been indexed and shows it on web pages by using Search Web Parts, like the Content Search WebPart. You brand content on the publishing site by using master pages, page layouts, and display templates.

In SharePoint 2013, cross-site collection publishing used to work out-of-the box. In SharePoint 2016, when integrating the catalog in a publishing site. No results are shown by the content search webpart that is added to the category page.

image

Although, in the properties of the webpart you will notice that the items from your catalog are in the search index. The webpart is not showing any items because it is additionally filtering the taxonomy managed property on the current and child navigation.

image

The reason that he is not showing any results in the content search webpart is caused by what I described in a previous blog post on auto generated managed properties in SharePoint 2016. Because they are not “activated” by default anymore, you have to create/activate them manually.

You can fix this taxonomy managed property in the search schema of the search service application using the following PowerShell.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"
$category = Get-SPEnterpriseSearchMetadataCategory -SearchApplication $ssa -Identity "SharePoint"
$crawledProperty = New-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $ssa -Category $category -VariantType 0 -PropSet "158d7563-aeff-4dbf-bf16-4a1445f0366c" -Name "ows_taxId_Genre" -IsNameEnum $false
$managedProperty = New-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $ssa -Name "owstaxIdGenre" -Type 1 -FullTextQueriable $true -Queryable $true -Retrievable $true -SafeForAnonymous $true
$managedProperty.Searchable = $true
$managedProperty.Refinable = $false
$managedProperty.Sortable = $false
$managedProperty.HasMultipleValues = $true
$managedProperty.OverrideValueOfHasMultipleValues = $true
$managedProperty.Update()
$mapping = New-SPEnterpriseSearchMetadataMapping -SearchApplication $ssa -ManagedProperty $managedproperty -CrawledProperty $crawledproperty

The PropSet ID will be “158d7563-aeff-4dbf-bf16-4a1445f0366c” since the cross-site collection category/navigation field is always a taxonomy field. To find the appropriate name for the crawled and managed property, you can search for them in the Search Schema of the Search Service Application using Central Administration. You can’t decide to rename this field because the cross-site collection configuration will be looking for this exact field. Other fields, part of your catalog, can be created with different names and used in the property mappings of the Content Search WebPart without any problem.

Don’t forget to start the crawler after having updated the crawled and/or managed properties.

Friday, May 5, 2017

Automatically created managed properties do not work OOB in SharePoint 2016

In this blog post I will discuss changes Microsoft made to the logic behind Crawled and Managed Properties in SharePoint 2016. In SharePoint 2013, crawled and managed properties were automatically created by the Search crawler. You could then immediately start using the auto generated managed properties in your search queries, they just worked out-of-the box. I admit, they did not look pritty, but in those cases, where pritty was important, you could manually create them with pritty names …

Now, since SharePoint 2016, those auto-generated managed properties still seem to be created but they are disabled. If you look at one such managed property, you will see an info message stating the following:

Automatically created managed property. ManagedPropertyOWSTEXT is an automatically created managed property. You can't see any of its existing settings or which crawled properties are mapped to it, but you can map more crawled properties to it. If you save the managed property without making any changes, all settings will be deleted.

Now what is happening here? Is this a bug in SharePoint 2016? No, it isn’t. Microsoft states that this is intended, and is inspired by how it is configured in SharePoint Online. You cannot see what the configuration is in the property, but you can change and save, overriding the “internal” settings.

But wait, be aware that when you change the settings of auto generated managed properties, those custom settings will be lost when, for some reason, you need to reset your search index…

Changes in PowerShell

Now, I’m used to provisioning my search schema with PowerShell. I never had any problems doing this in SharePoint 2013, I assumed that my PowerShell would still work in SharePoint 2016. But the CmdLets Get-SPEnterpriseSearchMetadataCrawledProperty and Get-SPEnterpriseSearchMetadataManagedProperty did not return any results. It feels like the automatically created crawled and managed properties are not there, while I can see them in the Search Service Application Search Schema.
The reason for this is that in SharePoint 2016, crawled and managed properties that were automatically created from custom columns become part of the Search Index instead of the Search Schema. And the PowerShell CmdLets mentioned above are querying those in the Search Schema.

The solution for this is to create the crawled and managed properties from within PowerShell. Assume the following crawled and corresponding managed property that you would like to activate using PowerShell:

  • MediaNameOWSTEXT (Managed property)
  • ows_q_TEXT_MediaName (Crawled property)

I used the following PowerShell to activate them:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Add-PSSnapin "Microsoft.SharePoint.PowerShell"

# Get the Search Service Application
$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"

# Get Search category (origin was a site column)
$category = Get-SPEnterpriseSearchMetadataCategory -SearchApplication $ssa -Identity "SharePoint"

# Create crawled property
# - PropSet:
#   - 158d7563-aeff-4dbf-bf16-4a1445f0366c - TaxonomyField
#   - fea84df6-a0fc-492c-9aa7-d28b8dcb08b3 - SPFieldMultiLineText, HtmlField, ImageField, LinkField
#   - ed280121-b677-4e2a-8fbc-0d9e2325b0a2 - SPFieldText, SPFieldChoice, SPFieldMultiChoice, SPFieldNumber, SPFieldCurrency, SPFieldDateTime, SPFieldBoolean, SPFieldUser, SPFieldUrl, SPFieldGuid
#   - 00130329-0000-0130-c000-000000131346 - other field types
$crawledProperty = New-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $ssa -Category $category -VariantType 0 -PropSet "ed280121-b677-4e2a-8fbc-0d9e2325b0a2" -Name "ows_q_TEXT_MediaName" -IsNameEnum $false

# Create managed property (Type 1 is Text, auto generated are always text)
$managedProperty = New-SPEnterpriseSearchMetadataManagedProperty -SearchApplication $ssa -Name "MediaNameOWSTEXT" -Type 1 -FullTextQueriable $true -Queryable $true -Retrievable $true 
$managedProperty.Searchable = $true
$managedProperty.Update()

# Map managed property to crawled property
$mapping = New-SPEnterpriseSearchMetadataMapping -SearchApplication $ssa -ManagedProperty $managedproperty -CrawledProperty $crawledproperty

You can ignore the warnings, this is because the parameters SearchApplication and VariantType are mandatory but ignored when called like above.