Category Archives: SharePoint

Tweaking the default search display template in SharePoint 2013

Let’s look at what it takes to make a minor tweak to the out of the box search result in SharePoint 2013. Say my requirement is to show the document id in the search result like the sample shown below.

Search Result

For the example above I’m going to create a custom display template for PowerPoint files.

Let’s start by mapping the display templates folder as a local drive. Browse to /_layouts/15/DesignMapDrive.aspx and click on the /_catalogs/masterpage/ link to open the drive. You can then map that as a network drive.

Through explorer browser to the \_catalogs\masterpage\Display Templates\Search folder and copy these two files file to a local drive.

  • Item_PowerPoint.html
  • Item_CommonItem_Body.html

Rename Item_PowerPoint.html to make it your own.

Open up the file and change the <title> node. This is what get’s displayed in SharePoint.

Make the changes highlighted below.

I’m basically updating the title in javascript to show the doc id. You would think this would be enough, unfortunately the render body method doesn’t seem to pick up the updated value. Instead you need to copy the entire div from the Item_CommonItem_Body.html file. Copy the Item_CommonItem_Body div from that file into your customised PowerPoint file and overwrite the line that makes the call to ctx.RenderBody.

DisplayTemplate

Upload your custom html file to Search display templates mapped folder.

Now browse to the Manage Result Types page from Site Collection Administration and make a copy of the Microsoft PowerPoint result type.

From the Actions drop down pick the display template that you just uploaded and your all set.

Things to watch out for when migrating SharePoint 2010 FAST Search to SharePoint 2013

I’m currently working on a Search First migration to SharePoint 2013. This post is a placeholder to document the gotchas and workarounds.

Search Centre Keywords

Our initial plan was for a search-first migration where we would swap out the FAST search service application for an SP2013 search service application. The idea was that we would make no changes to the existing search centres but they would get a better/fast search engine with all the improvements that come in 2013.

Issue: Keywords defined in the SP 2010 Search Centre are ignored by SP2013 Search. The only way this functionality can work is when you use a SP2013 search centre. This is not a problem if you have only one search centre since you can manage the keywords at a farm level but we had a number of search centres with site collection admins needing the ability to manage the keywords for the site they manage.

Workaround: We were forced to create Search Centres in SP 2013 and have the SP 2010 sites use the new search centres.

XSLT to Display Templates

Given that we were on the path to using SP2013 search centres any customisations that were made to the SP2010/FAST search XSL now needs to be re-written as Display Templates. In a way this is better than having to mess with XSL, but this is still something that you need to take into account.

 

Making SharePoint JSon calls from PowerShell in SharePoint 2013

The Invoke-RestMethod in PowerShell 3 doesn’t send the appropriate header required by SharePoint 2013 to return JSon results. It took me a while to figure out this workaround.

$parameter = "my search text"
$encParam = [System.Web.HttpUtility]::UrlEncode("'$parameter'")  
$url = "http://mysp2013site/_api/search/query?querytext=$encParam"  
$wc = new-object System.Net.WebClient  
$wc.UseDefaultCredentials = $true  
$wc.Headers.Add("Accept", "application/json; odata=verbose")  
$res = $wc.DownloadString($url)  
$res

Tips for working with BCS and FAST Search

When building a FAST search solution to crawl external entities through BCS it can get very frustrating if you deploy a change and it doesn’t get updated in all the right places.

After much trial and error I have come up with the following checklist to keep your sanity.

Rule #1: If you change the BCS model manually (i.e. using a text editor instead of Visual Studio) you need to change the Version attribute of the Entity node in the entity that you make the change in. If you don’t do this any update you make will not be applied. This can lead to very confusing behaviour since the change you made will get reflected at some point down the line.

Apart from that here goes the checklist

  1. Delete the BCS content source
  2. Restart the SharePoint Server Search service
  3. Using Task Manager kill off any mssdmn.exe that are running
  4. Deploy your updated solution
  5. Recreate the content source and run a full crawl.

If your working in a multi-farm scenario where the Search service is in a different farm to that of the BCS service then you need to do steps #2 & #3 in the server running the Search crawls. This is important because any assemblies that you have built for the entity are dynamically copied into that server and loaded into Server Search & mssdmn.exe.

If you don’t do steps #2 & #3 Search will end up using the older version of your assembly and not the one that you just deployed.

Feature differences between SharePoint 2007 Enterprise and Standard for a Publishing Portal

I recently had to deploy a site template that was built using SharePoint Enterprise Edition 2007 on an instance of SharePoint Standard Edition 2007.

Obviously given that some features were not available in the Standard Edition I received the ‘The template you have chosen is invalid or cannot be found’. Unlike a MOSS to WSS conversion the problem here is that the features do exist on the server but are simply not available for the standard edition.

I basically resorted to manually comparing the differences between a site template created in the Standard edition vs one created in the Enterprise edition.

Here’s the list if anyone ever needs this.

Remove these features from a template created in the Enterprise edition if you want to deploy it on a Standard edition. Obviously you need to test to ensure that your template is not actually using any of the Enterprise features.

<Feature ID="065c78be-5231-477e-a972-14177cc5b3c7" />
<Feature ID="0806d127-06e6-447a-980e-2e90b03101b8" />
<Feature ID="2510d73f-7109-4ccc-8a1c-314894deeb3a" />
<Feature ID="e8734bb6-be8e-48a1-b036-5a40ff0b8a81" />
<Feature ID="00bfea71-dbd7-4f72-b8cb-da7ac0440130" />

Workflow does not start automatically when bulk inserting items

This had me tripped for a while. I was bulk inserting items (~800) to a list which had event receivers as well as a workflow attached.

The problem was that the workflow was not being triggered. Or if it did it just hung at In Progress.

After poking around for more than an hour I discovered that if I inserted a single item it worked. So to fix the issue I added a ten second sleep (Thread.Sleep) between the inserts and the workflows are triggering away happily.

Implementing Business Rules in a SharePoint list

On the project I am currently working on I had to implement a custom business rule for a list. The requirement was that only users in an Administrator group should be allowed to edit a particular field. All other users can edit that list but they are not allowed to touch that particular field.

Given that this was the first time I had to do this in SharePoint I did some research to figure out the best practice but came up empty. Most of suggestions were to customize the edit form and add the logic there. This clearly will not work since the business rule validation is in the UI and not in the actual list. Hence leaving it open for anyone to open in datasheet view or any of the other numerous ways (e.g. web services) to break the business rule.

[Note: While researching for this post I did come across the ‘Enforcing Custom List Item Data Validation’ best practice by SharePoint patterns and practices group, which essentially makes the same recommendation as this blog post.]

SharePoint 2010 makes it a little easy with the Validation Formula feature which lets you add business rules to any list directly from the UI. But with SharePoint 2007 you’ll need to use an SPItemEventReceiver to implement your business rule.

There is a good code sample on validating a list in the List Item Event Receivers article on TechNet.

Write CAML queries in code

In my very first webpart that I wrote I needed to write some CAML queries to filter and sort the lists.

Being the type of guy who hates seeing strings littering my code I searched the net for an API for CAML queries. Thankfully John Holliday had already done the hard work and created CAML.NET. Check out the clean syntax for the CAML code.

   1: string typeName = "My Content Type";
   2: string simpleQuery =
   3:     CAML.Query(
   4:         CAML.Where(
   5:             CAML.Or(
   6:                 CAML.Eq(
   7:                     CAML.FieldRef("ContentType"), 
   8:                     CAML.Value(typeName)),
   9:                 CAML.IsNotNull(
  10:                     CAML.FieldRef("Description")))),
  11:         CAML.GroupBy(
  12:             true,
  13:             CAML.FieldRef("Title",CAML.SortType.Descending)),
  14:         CAML.OrderBy(
  15:             CAML.FieldRef("_Author"),
  16:             CAML.FieldRef("AuthoringDate"),
  17:             CAML.FieldRef("AssignedTo",CAML.SortType.Ascending))
  18:     );

Here again you might run into the issue of adding an extra assembly to your deployment, the simple alternative that I took was to include the CAML class directly into me source tree. But remember to keep the copyright and license header in place as stated by the Ms-CL license.

Hopefully Microsoft will release a Linq to CAML library soon, there is already one at CodePlex by a Microsoft employee but what would be better is if it comes with SharePoint.

Getting ModifyUserPropertyByAccountName to work

The documentation for the ModifyUserPropertyByAccountName method of the UserProfileService in the SharePoint Server SDK has a bug.

You’ll notice that although there are no errors reported the profile doesn’t get updated. The fix is quite simple though and is actually present in the other examples. Setting the IsValueChanged to true does the trick.

Here’s how the corrected code looks like.

   1: namespace ModifyUserPropertyByNameSample
   2: {
   3:     class Program
   4:     {
   5:            
   6:         static void Main(string[] args)
   7:         {
   8:             //Instantiate the Web service. 
   9:             UserProfileService userProfileService = 
  10:                 new UserProfileService();
  11:  
  12:             //Set credentials for requests.
  13:             //Use the current user log-on credentials.
  14:             userProfileService.Credentials =
  15:                 System.Net.CredentialCache.DefaultCredentials;
  16:  
  17:             PropertyData[] newdata = new PropertyData[1];
  18:             newdata[0] = new PropertyData();
  19:             
  20:             newdata[0].Name = "FirstName";
  21:             newData[0].IsValueChanged = true;
  22:  
  23:             newdata[0].Values = new ValueData[1];
  24:             newdata[0].Values[0] = new ValueData();
  25:             newdata[0].Values[0].Value = "Mark";
  26:  
  27:             // TODO 
  28:             // Replace "domain\\username" with valid values.
  29:             userProfileService.ModifyUserPropertyByAccountName
  30:                 ("domain\\username", newdata);
  31:  
  32:         }
  33:     }
  34: }

 

For what it’s worth I’ve uploaded a working solution to the MSDN Code Gallery that allows you to view the current profile data and make changes by providing the name/value pair through the query string. You can download the SharePoint Profile Updater here.