Archive

For our projects we always try to avoid manual configurations. This is because it is a tedious and error prone process if you work with a DTAP environment. To avoid this, we also try to script as much as possible for SharePoint Online projects. Lately we worked with creating lookup fields in SharePoint online, using PowerShell and CSOM. Creating fields this way is pretty easy, but connecting lookup fields forced us to think about casting the Microsoft.SharePoint.Client.Field object to a Microsoft.SharePoint.Client.FieldLookup object.

Within CSOM this can be done by leveraging the ClientRuntimeContext.CastTo method, but… This is a generic method (object of type T). This is something which is not easily supported by PowerShell. To use this method, you can use reflection using the MakeGenericMethod method.

Lately I’ve been working a lot with custom display templates and custom refiners. This worked all pretty well, I could update the look and feel by changing the body without any problem. However, when I made changes in the head section of the display template, this didn’t seem to reflect my changes… And there you update your Managed Properties and in my case I also added some logic to retrieve some variables.

Using the debugger of Internet Explorer I saw the old version of the Javascript files were still used for the display templates. Somehow these where cached… The URL of my display template ended with ?ctag=122$$15.0.4481.1005. Well this number of course can change, but somewhere the old version was still in the SharePoint cache. This led me to look at my Result Types, since my display templates are used based on those…

On the top of the page I found the following message:

Just click the Update link and you will get the following message:

Refresh your search result page and the latest version of your display template will be used!

For now the last section about generating documentation for your custom SharePoint solution. The following PowerShell scripts will provide you with an overview of activated features on your Farm, WebApplication and Site Collections. Since this script is meant for custom solutions, I assume you have used a prefix (Visual Studio adds the solution name by default as a prefix to all features).

Sometimes you want an overview of your custom farm solutions which are deployed on your farm. Normally I prefix all my solutions to make it clear who created them. Using this prefix you can easily run a PowerShell script which provides you with a list of installed solutions and the web applications to which these solutions are deployed:

Sometimes during SharePoint development item are programmatically added to SharePoint based on for example the title of the site, which can contain special characters. This can occur when creating documents, SharePoint groups etc. You will receive a message stating that the following characters are not allowed: / \ [ ] : | < > + = ; , ? * ‘ @

In my case I wanted to create custom SharePoint groups based on the title of the web. To avoid these errors when characters like that are used in the Web title, I’ve used a regular expression to remove these characters. This can be accomplished by the following lines of code:

For my projects I always provide documentation about the solutions our team has developed. Part of the development is an overview of the features which are added to the different solutions. This because most of the features tend to be hidden and the customer and administrators will not use Visual Studio to check which features are added.

As most developers I don’t like to document everything twice and on multiple locations. All features in my project are already documented in Visual Studio. I’ve added titles, images, descriptions etc. This information can easily be reused to generate documentation about the features. For that, I use the following PowerShell script:

# Set the feature folder based on the SharePoint version$featureFolder=“C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\FEATURES”

# Provide a prefix to filter the set of features$featureFolderPrefix=“Macaw.”

When you’ve added the custom ranking model to SharePoint, you can use it using a query string parameter called rm1. But that doesn’t really look nice, and when people don’t use that query string variable, they will end up using the default raking model again.

It does look like you can set it as the default raking model by tweaking the properties of the Core Result WebPart. It has a property to set the default ranking model, but…. It doesn’t seem to work for the People Search. The People Search will keep setting the ranking model back to the default people search ranking model MainPeopleModel.

So where does this leave us… We can still use the query string option and we can off course always use a JavaScript on the page to redirect using the query string variable if it is not set. But, that does mean we can get useless hits on the page and useless search queries (since we redirect the user right after their request). This is something I really don’t like… It causes load on the servers which should not be there.

To get around this issue, I’ve created a small WebPart. The WebPart allows you to provide the ID (GUID) of a custom ranking model and during the initialization of the page, it sets the custom ranking model for the query manager of the page. This ensures that the search query will use your custom ranking model, without performing useless queries or redirecting the user. The code to get this working you can find below. Please note, I’ve added my own logging module to this code and you probably want to add your own logging logic J.

namespace PeterHeibrink.SP2010.Intranet.WebParts.WebParts.SetSearchRankingModel{///<summary>/// This class implements a <see cref=”WebPart”/> which allows for/// overriding the ranking model ID.///</summary>///<remarks>/// This WebPart is needed for applying a custom ranking profile for people search./// For people search, the default ranking model setting in the WebPart properties is/// not persisted and cannot be set by updating the WebPart XML.///</remarks>

///<summary>/// This property allows for setting the Ranking Model ID///</summary>///<remarks>/// This is used to force the search webparts on the page to use/// an alternative ranking model. This is done because the people search /// webpart will otherwise not use a custom ranking model.///</remarks>[WebBrowsable(true), WebDisplayName(“Ranking model ID”),WebDescription(“This should be the ID of the ranking model”)][Personalizable(PersonalizationScope.Shared),SPWebCategoryName(“Ranking model”)]publicstring RankingModelId

{get { return _rankingModelId; }set { _rankingModelId = value; }

}

privatestring _rankingModelId = string.Empty;

#endregion

#region Overriden events

///<summary>/// This event will ensure the <see cref=”QueryManager”/> will use a custom/// ranking profile.///</summary>///<param name=”e”>Event arguments</param>protectedoverridevoid OnInit(EventArgs e){// Makse sure the property is setif (string.IsNullOrEmpty(RankingModelId)){

LogService.LogWarning( LogCategory.WebPart,“An WebPart has been added to override the Ranking Model of a Search Query, but no Ranking Model ID has been provided.”);return;

}

// Get the current query manager and make sure it is availableQueryManager queryManager = SharedQueryManager.GetInstance(this.Page).QueryManager;if (queryManager == null){LogService.LogError(LogCategory.WebPart,“An WebPart has been added to override the Ranking Model of a Search Query, but there is no Query Manager available.”);

return;}

// Set the custom ranking model for all locationsforeach (LocationList locationList in queryManager)foreach (Location location in locationList)location.RankingModelID = RankingModelId;

LogService.LogMedium(LogCategory.WebPart,“An WebPart has been added to override the Ranking Model of a Search Query, the locations have been updated with the new ranking model.”);

base.OnInit(e);

}

///<summary>/// This event will add a control to the page displaying the ranking model setting.///</summary>///<remarks>/// The Ranking model is displayed to allow for easy checking if the webpart is added on the page/// by accounts without permissions.///</remarks>