Friday, July 14, 2017

Adding custom managed properties to the default display templates – the quick and dirty way for non-developers with little time on their hands

Yesterday I was helping another consultant with some search rank issues. We had an hour scheduled and managed to resolve the ranking well enough. But then I got the question, do we have time to add some custom data to the results? Ouch! Something which sounds easy, and is not done in 5 minutes. Turns out after I gave it some thought on an upset stomach due to a bad kebab yesterday, it is actually a 5 min task when you know how.

Read on!

The search page was a typical custom search page created in a team site as a web part page, with three search web parts and a scoped query. Very easy to set up in a few minutes. The results were Office documents and PDF’s scoped to a few specific locations.

image

There are numerous posts out there on how to add custom managed properties, but that involves duplicating all the default display templates, or creating a mother of all template which renders all file types the way you want.  If you try to modify one of the default display templates to add your custom managed property, it just won’t load.

So why this post? Well, I’ll let you know how you indeed can modify the default templates, and still get your custom managed property to render. It might not be the proper or recommended way, but it works and will save non-devs tons of time making minor changes to the search results.

A typical result looks like the image below, and we want to add some piece of metadata at the red arrows.

imageShow me how already, will you!

Start off with downloading a copy of Item_CommonItem_Body.js from /_catalogs/masterpage/display%20templates/search/item_commonitem_body.js in your site collection. This is a shared template used by all the other ones.

Around line 120 (at least on my recent download), add the code to show after the path in green. As my example I’m adding values from a managed property named encoding, which is not one of the default ones available in the results. I do this my adding the highlighted line below:

ms_outHtml.push('       '
,'            <div id="', $htmlEncode(id + Srch.U.Ids.preview) ,'" class="ms-srch-item-previewContainer"> '
,'                ', previewHtml ,''
,'            </div>'
);
        }
        
        ms_outHtml.push('Encoding:' + $getItemValue(ctx, "encoding"));
        
ms_outHtml.push(''
,'    '
);

Upload the updated Item_CommonItem_Body.js, overwriting your existing one. Make sure it’s published.

Your results will now show the label, but no value for encoding.

image

So how do you ensure loading of your custom properties? Basically you modify a web part property called SelectedPropertiesJson on the search result web part. You can download the .webpart file and modify it manually, or you can for example use PnP PowerShell.

image

The below code ensures loading of two managed properties, encoding and refinablestring100.

Connect-PnPOnline -Url https://tenant.sharepoint.com/sites/searchsite

$webPartName = "Search Results"
$pageUrl = "/sites/test2/SitePages/My Search Page.aspx"

$wpId = (Get-PnPWebPart -ServerRelativePageUrl $pageUrl |? {$_.WebPart.Title -eq $webPartName}).Id
$myProps = @("encoding","refinablestring100")
$json = ConvertTo-Json $myProps -Compress
Set-PnPWebPartProperty -ServerRelativePageUrl $pageUrl -Identity wpId -Key "SelectedPropertiesJson" -Value $json

If you refresh the search result page, it’s now also displaying your custom properties!

image

Wednesday, July 12, 2017

Every (blank) pixel counts! - Minor quirk on custom ribbon action icons in modern lists

Typically the icon for a custom ribbon action in classic pages is 32x32 pixels. On modern lists the icon however is 20x20 pixels. If you use a 32x32 pixel image this is what it will looks like in classic and modern view.

image

Notice in modern view how the icon goes below the base line of the default ribbon icons, and that the icon is a little fuzzy. This is due to scaling 32x32 down to 20x20, which is not a direct pixel multiple. The solution is to pad the 32x32 image to 40x40. Keep the icon the same size, but increase the white space.

Original 32x32 icon

image

Padded 40x40 icon

image

In classic mode, the icon will look the same due to the use of CSS to position the image, where any overflow is hidden. In modern view however we now get a crisp image aligned with the existing icons. The crispness is due to the image being 40x40 pixels, and divided exactly in half – which avoids pixel smoothing on resize.

image

This might not be a big deal, but every pixel counts right? Winking smileGoing forward for modern pages you would use SharePoint Framework extensions for ribbon actions instead which allows the use of Office UI Fabric font icons instead of image files.

Monday, July 10, 2017

Querying managed metadata using REST (unsupported)

I’m working with a set of SharePoint framework web parts and finally got fed up of using JSOM to work with managed metadata. Referencing JSOM feels wrong for so many reasons in this modern day and age, so I’d rather not do it.

I mean, when the out-of-the-box modern controls in SharePoint can work with terms using REST, why shouldn’t I? I like to believe I’m pretty modern.

image

After Fiddling the modern UI I found out that all taxonomy requests are working against a service at /_vti_bin/TaxonomyInternalService.json. This is a good old service, also listed on MSDN at https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.taxonomy.webservices.taxonomyinternalservice_methods.aspx. It is indeed marked for internal use, and until we get a new public REST point, everything points to that it should indeed work. If not, why would Microsoft use it themselves?

I have put together a sample SPFx web part based on the MSDN documentation, trial and error, showcasing different methods I found useful when retrieving terms. It’s by no means complete, but should help you get started.

You can find the sample at https://github.com/wobba/spfx4fun/tree/master/react-taxonomy-rest (link to all methods)

Samples include:

  • List term stores
  • List term groups in a term store
  • List term sets in a term group
  • Search for term by label
  • Search for term sets by name of term set or term in set
  • Get level one terms of a term set
  • Get child terms for a term

Using these calls you should have enough information to build a metadata driven megamenu, or build a taxonomy picker.

I have included interfaces for all the REST calls with some comments, but not for the returned results. You might have to examine the result JSON and pick out what you need.

And as a nugget I output the JSON with indentation, a tip I picked up from Sahil Malik :)

Sample interface

interface IGetSuggestionsRequest {
  start: string; // query
  lcid: number;
  sspList: string; // guid of term store
  termSetList: string; // guid of term set
  anchorId: string;
  isSpanTermStores: boolean; // search in all termstores
  isSpanTermSets: boolean;
  isIncludeUnavailable: boolean;
  isIncludeDeprecated: boolean;
  isAddTerms: boolean;
  isIncludePathData: boolean;
  excludeKeyword: boolean;
  excludedTermset: string;
}

Friday, July 7, 2017

A first look at the layout options in Communication Sites

Note: This article is based on the preview of Communication Sites

Microsoft announced the preview of Communication Sites in first release a little over a week ago. At first I was expecting more, but after playing more with it, it’s actually a pretty good preview when it comes to content layout. And with the new Hero web part, which let’s you manually highlight content/links, creating a nice looking landing page is much easier than before.

image

The main difference between a Communication site and a Modern site as far as I can tell are that a comm sites have no left navigation, and you have the option to enable commenting on the pages you create.

Thursday, July 6, 2017

Getting URL query parameters when working in the SharePoint Framework

Image result for upper lower case p

Fetching values from the query string of the URL is something developers are constantly doing, as in this sample URL where I have two parameters, mvp and status.

https://madcow.sharepoint.com/?mvp=mikael&status=awesome

What you can use is the URL object in JavaScript which is still in a proposed spec.

The URL object is not fully supported by all browsers yet (looking at you Microsoft), but fortunately SPFx provides a polyfill for the URL object so it will work fine in IE10 as well.

There is however a small issue. Currently SPFx uses TypeScript v2.2.2, which access the query parameters with searchparams (lowercase p) instead of searchParams (uppercase p). This means that to avoid an error in VSCode or when building you need to use the lowercase p version – but this breaks in browsers which expect the uppercase p version *sigh*.

TypeScript v2.3.4, for example, support the uppercase p version just fine. So until SPFx bumps the TypeScript version to something supporting the uppercase p version, a workaround is to use the any keyword in TypeScript at the cost of loosing intellisense, but it works.

const url : any = new URL(window.location.href);
const mvp = url.searchParams.get("mvp");
const awesome = url.searchParams.get("awesome");

This way you won’t get errors when building your SPFx solution, nor in any browsers. Happy query parametering – or write your own parser (or as Waldek Mastykarz said when chatting on this, use left-pad :)

Wednesday, July 5, 2017

Getting signalR to work with the SharePoint framework

image

I’m creating a web part which will talk to a signalR back-end service for some document archiving with SharePoint. signalR on the client requires jQuery, which is the tricky part. I tried a few things without getting it to work, but turns out it’s not too hard to get working when you have Waldek Mastykarz on speed dial, so this post is mostly his work :)

First off you need to include signalR, and I picked the un-official npm package ms-signalr-client. Add it with:

npm i ms-signalr-client -save

I had already read Waldek’s post about how to include jQuery as an external reference, but it didn’t “just” work. This was the point where I called up Waldek.

By using Rencore’s script checker, we found out that signalR was a non-module, and that it requires jQuery to be available on the $ sign. To make this work I had to change the globalName reference in config.json of my SPFx project to $ instead of jQuery.

"externals": {
    "jquery": {
      "path": "https://code.jquery.com/jquery-2.1.1.min.js",
      "globalName": "$"
    }
}

and in my .tsx file I had to add the following imports:

import * as $ from 'jquery';
import 'ms-signalr-client';

I could now instantiate signalR as easy as pie in my code.

let connection = $.hubConnection(https://myserver/, { useDefaultPath: false });

Friday, June 23, 2017

Rendering Related Items as links in SharePoint (classic lists)

I’m doing minor work on a SharePoint 2013 installation every now and then and got a request to render the Related Items column introduced in SharePoint 2013 as an actual link instead of showing the text 1 related items.

The customer is running a workflow for approval and the task list looks like this by default.

image

If you go to the view form of the item you get a link to the related items, but having this in the list view would be preferable.The end result after applying custom rendering of the field looks like the image below. Why Microsoft decided not to render out the link by default is a mystery, but could be developer design ;)

image

An answer at SharePoint Stack Exchange had the answer, but did not complete the puzzle 100%.
Note: DO NOT do as the link in that answer points to, which is basically replacing the oob .js file for related items rendering. If you want to discuss why this is a bad idea, hit me up on twitter or fb.

Use rights for on-premises of SharePoint, Exchange and Skype for business - when you have Office 365 user licenses

This topic has been covered before (here and here), but I was recently in a conversation where this was brought up, so thought I’d do a short refresh.

To sum it up quickly; you need to purchase server licenses for your products, but depending on the Office 365 licenses you have, they cover on-premises usage rights for your employees, so no need to purchase duplicate CAL’s.

It’s all listed in the Product Terms document which you can download from https://www.microsoft.com/en-us/licensing/product-licensing/products.aspx. The document covers use rights for other products as well and is the go-to guide on licensing.

image

In the latest version dated June 1st, 2017 a fair bit down in the SharePoint section you see that SharePoint Online Plan 1 cover standard licenses and Plan 2 cover enterprise features of SharePoint 2016 on-premises. This means, you still need to purchase the appropriate server licenses, but if you have Office 365 E1-E5 licenses, you are covered on the user licenses – as E1-E5 cover SharePoint Online Plans. E1 only covers base or standard SharePoint features (see table at the end).

image

You can find the same information in the document for licenses regarding Exchange and Skype for business. There’s also a note pointing to Appendix A which puts it all in a nice table, and I’ve highlighted the ones for SharePoint use right as an example. The top row lists all the different licenses you can have for users, and the blue squares show where they apply as valid on-premises licenses.

The Base entry is standard functionality, and the additive is for enterprise functions.

image

This means that if you have an Office 365 E1 license, you can use SharePoint Standard functionality, while E3, E4 and E5 give you usage rights to Enterprise features as well like enterprise search, e-discoery, InfoPath services etc, all listed in 3.2.1 in the first image.

Tuesday, June 20, 2017

Re-introducing Microsoft Forms

About a year ago I wrote a post outlining the Microsoft Forms functionality which at the time was available only to educational tenants (EDU license).

This time around Microsoft has decided to launch a preview of the same functionality to enterprise tenants as well – and about time as it’s a nice little application indeed.

So what is Microsoft Forms? It’s an application to create simple forms, surveys and quiz's. It’s not a replacement for InfoPath, it’s not a replacement for PowerApps, but it sits somewhere in-between, and is really easy to use.

Read my original post for an in-depth review

Thursday, June 15, 2017

How to remove the banner on modern pages from the UI

I have previously written about how to change the layout type of a modern page using PnP PowerShell in order to get rid of the huuuuge top banner. Yes,  I know Microsoft is in the works of adding functionality to the UI to allow header changes, but until that happens I figured I’d show a way to accomplish the same for a Power User.

The layout of a modern page is handled by a column named Page Layout Type (PageLayoutType), and it’s part of a sealed content type named Site Page.

You cannot modify a sealed content, and the Page Layout Type column is hidden, so we need a tiny bit of trickery to get this working.

In your site, navigate to site settings, and to site site content types. Or tack /_layouts/15/mngctype.aspx at the end of the URL to go there directly.

Create a new content type named My Site Page which inherits from the Site Page content type.

image

Copy the content type id from the URL in your browser and create the following URL:

https://contoso.sharepoint.com/teams/modernisthenewmodern/_layouts/15/ManageContentTypeField.aspx?ctype=0x0101009D1CB255DA76424F860D91F20E6C411800FA0F5B1F8210094AB33AED9F195597A5&Field=PageLayoutType

On the column screen, make no changes, just hit OK. This will make the column visible later. Next, navigate to the Site Pages library and go to library settings and add the previously created content type.

image

You are now ready to create your site or news page. Once the page is created and saved:

  • navigate back to the site pages library
  • select the page you created
  • click the information icon
  • change the content type to My Site Page

You will now see the Page Layout Type column visible. Change the value from Article to Home, and the banner is gone. You can change the content type back to Site Page after you have changed the layout to ensure any search based experience relying on the base type is still working.

image

Look ma, no banner!

image

Summary

Once set up, you can per page change the content type to your custom one and change the layout to get rid of the banner. It’s somewhat convoluted, but it is doable from the UI :)