Wednesday, November 16, 2016

Displaying a random SharePoint Search result using Display Templates

On a recent project I had the requirement to randomly display a staff profile on the home page of the Intranet. The staff profile would provide some basic details of the person (with a head shot), then on clicking the item the user would be redirected to a page that displayed a bunch of fun questions and the person's response to each question. The web page used its own custom page layout and associated content type to store all of the answers.

Now we've probably all seen various custom developed web parts in the past, utilising calls to the User Profile Service or some other list via CAML queries. We've probably also seen Content Query Web Part solutions. For this project I was determined to leverage search as much as possible, reducing the continual queries to the backend data source. So my technical challenge was not in getting the results (as search query rules/result sources do a good job of that); but rather randomly selecting an item to display from the result pool.

So in order to make this magic happen, I went about with the idea of creating a custom group display template (i.e. to generate the seed) and a custom item template, whose job was to render the item if it was told to do so. So how do you do this? Quite simply, you add your own variables to the Search context!

In your control template, you put the following :

<!--#_
        var randomItem = 0;  // default to first item returned from search
        try {
            var totalResults = ctx.ListData.ResultTables[0].ResultRows.length; //get the total number of results returned
            if (!isNaN(totalResults))
            {
                randomItem = Math.floor(Math.random() * totalResults);
            }
            ctx.RandomItemNumber = randomItem;  // prime our own variable for the Item display template
        }
        catch (err) {
            console.log(err);
        }
_#-->

Then in your item template, you put the following around the outer part of the display template:

<!--#_
  var showItem = true;  // default to showing the item
  try
  {
       if (ctx.CurrentItemIdx != ctx.RandomItemNumber) {
                showItem = false;
       }
  }
  catch (err)
  {
       console.log(err);
  }
  if (showItem)
  {
 _#-->
...Your Item output rendering goes here...
<!--#_
  }
_#-->

I hope this helps someone - it took a little bit of playing around to discover how to get this working, but in the end it was really quite simple.

Friday, March 27, 2015

Get all Office 365 Video Channels, Groups and Delve Boards with REST

​source: http://www.vrdmn.com/2015/01/get-all-office-365-video-channels.html

Office 365 has introduced 3 new portals recently: Videos, Groups and Delve. Behind the scenes, the architecture of Videos and Groups is such that each Video channel is a site collection and so is each Group. For Delve boards, each board is saved as a Tag and when you add a document to a board, the document is tagged with the name of the board.

If you are working on a solution for Office 365 and want to integrate Videos, Groups or Delve, here is how you can get a list of all of them using the SharePoint REST API:

1) Get all Office 365 Video Channels with REST API:
https://siteurl.sharepoint.com/_api/search/query?querytext='contentclass:sts_site WebTemplate:POINTPUBLISHINGTOPIC'&SelectProperties='WebTemplate,Title,Path'&rowlimit=50

2) Get all Office 365 Groups with REST API:
https://siteurl.sharepoint.com/_api/search/query?querytext='contentclass:sts_site WebTemplate:Group'&SelectProperties='WebTemplate,Title,Path'&rowlimit=50

3) Get all Delve Boards with REST API:
https://siteurl.sharepoint.com/_api/search/query?querytext='(Path:"TAG://PUBLIC/?NAME=*")'&Properties='IncludeExternalContent:true'&selectproperties='Path,Title'&rowlimit=50

SharePoint 2010 Public Site Navigation not working on latest version of Safari for the Mac

The link below provides the fix, which is an update to the compat.browser file.
http://blog.sharepointexperience.com/2014/10/did-safari-or-ios-8-break-your-sharepoint-2010-site/

Wednesday, October 24, 2012

onclick attributes do not fire on custom search XSLT on a Publishing page

I had a requirement for a client this week to create a search solution for a custom list (for Contractors). Basically the client wanted to use SharePoint Search and a custom XSLT to render the list items. The two challenges I faced (without reverting to full on development):
  1. Make the results sort by the Company name. Note that OOB, the Core Search Results web part does not support this. It only supports sorting by date or relevance (which is the default).
  2. Open the results in a modal popup window, rather than redirecting the whole page to the list item.

To solve point 1, I found the blog entry http://ddkonline.blogspot.com.au/2011/12/sharepoint-2010-modifying-core-search.html which allowed me to change the sort order to company.
The second problem was more frustrating to solve. I thought that within the XSLT I would add the onclick element, calling a function to load the given URL into a SharePoint modal window. But every time I tried, the onclick event just wouldn't fire. I went back to simple onclick="alert('hello')" and it still didn't work.  Within the body of the page I added straight links, switched to HTML mode and added the onclick events there, but every time I did this, SharePoint would strip it out. The blog entry at http://blog.mastykarz.nl/tracking-links-google-analytics-sharepoint-2010-mavention-google-analytics-links-tracking/ then gave me a clue. Basically SharePoint was blocking basic onclick events from firing or removing them all together. So to solve the problem, I removed the onclick attributes, then embedded a jquery function within the XSLT to iterate through all links and add the onclick event. This time it worked. FYI, below is the XSLT block:   

<xsl:text disable-output-escaping="yes">  
<![CDATA[  
<script type="text/javascript" src="/_layouts/Inflow/cqwp.js"></script>  
<script type="text/javascript">  
$(document).ready(function () {    
  if ($("#results-table").length) {  
    $("#results-table a").click(function() {   
      openDialog($(this).attr('href'));   
      return false;  
    });    
  }  
});  
</script>  
]]>  
</xsl:text>  
<div class="srch-results" accesskey="W">  
<table id="results-table" border="1"> <tr><th>Company</th><th>Active / Inactive</th><th>Full Name</th></tr>  
<xsl:apply-templates select="All_Results/Result">    
<!-- The xsl-sort needs operate upon a single field - it doesn't work if the sort has to evaluate child nodes-->    
<xsl:sort select="company" />  
</xsl:apply-templates>  
</table>  
</div>  
<xsl:call-template name="DisplayMoreResultsAnchor" /> </xsl:template>
<!-- This template is called for each result -->
<xsl:template match="Result">  
<xsl:variable name="id" select="id"/>  
<xsl:variable name="currentId" select="concat($IdPrefix,$id)"/>
<xsl:variable name="url" select="url"/>
<tr><td>
<a id="{concat($currentId,'_Title')}">          
<xsl:attribute name="href">            
<xsl:value-of select="$url"/>          
</xsl:attribute>          
<xsl:attribute name="title">            
<xsl:value-of select="company"/>          
</xsl:attribute>         
<xsl:value-of select="company"/>        
</a>
</td>
<td><xsl:value-of select="activeinactive" /></td>
<td><xsl:value-of select="fullname" /></td>
</tr>
</xsl:template>
 

Monday, September 24, 2012

How to fix “Add Host to Workflow Farm problem” when installing Windows Azure Workflow in SharePoint2013 Preview

I had this issue today when installing Windows Azure Workflow in my SharePoint 2013 environment.

In my case, the error message was as follows:
System.Management.Automation.CmdletInvocationException: Could not successfully create management Service Bus entity 'WF_Management/WFTOPIC' with multiple retries within timespan of 00:02:05.5769235. ---> System.TimeoutException: Could not successfully create management Service Bus entity 'WF_Management/WFTOPIC' with multiple retries within timespan of 00:02:05.5769235. ---> System.UnauthorizedAccessException: The remote server returned an error: (401) Unauthorized. Authorization failed for specified action: Manage..TrackingId:3e0f0351-14d0-4620-b80e-c506156b6f7a,TimeStamp:9/24/2012 1:15:07 AM ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.

Other posts talk about ensuring your RunAs account uses a FQDN. E.g. sp_content@wingtip.com, which I had been doing. Instructions from CriticalPathTraining also say that this account should have dbcreator and securityadmin rights at the SQL level, that TCPIP should be enabled through SQL Configuration Manager, and that the RunAs account is a member of the local administrator group (which it was).

To fix this, I first went to each of the workflow databases and explicitly set the membership for the sp_content database so that it had db_owner and also was a member of the respective application roles that had been created for each database. E.g. Store.Operators and Store.Administrators in the SbManagementDB database. I then logged into the SharePoint server as the sp_content account and re-ran the Workflow configuration to join the existing farm. This time it worked!

Sunday, July 24, 2011

SharePoint Search Exception: The server did not provide a meaningful reply

Recently I had to configure search sometime after the initial build, which was done using AutoSPInstaller. To ensure consistency of approach, I created a slightly modified version of AutoSPInstallerMain.ps1 and also XML AutoSPInstallerInput files. The only real difference in the XML file was that I was instructing AutoSPInstaller to provision search, and also that I was instructing it to not provision Central Admin (as this was already provisioned and I have experienced the script failing when CA had already been created). The main difference in the AutoSPInstallerMain.ps1 was that I commented out a lot of the entries in the Setup-Services function (i.e. to only run StartSearchQueryAndSiteSettingsService and CreateEnterpriseSearchServiceApp).

Shortly after the installation/configuration of Search, users were experiencing a correlation exception when performing searches. The ULS log returned the error 'Internal server error exception: System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.'. Subsequent messages also included 'A runtime exception was detected. Details follow. Message: Thread was being aborted'.

To fix this issue I had to do the following:
1) On each SharePoint Server, modify the permissions to the C:\Windows\Temp directory to ensure that the WSS_WPG group had both read and write access (by default after the Search installation, this group only had read access)
2) Restart the 'SharePoint Server Search 14' search on each server.

Once this was done, search began to work. Hope this helps someone.

Saturday, May 07, 2011

Upgrading a Custom Search Results XSLT from 2007 to 2010

Whilst upgrading a public web site that I had previously created in SharePoint 2007, during testing I noticed this strange number appearing at the end of my upgraded search results page. After the last result I was seeing a number like 68050. This number changed as I performed more searches.
I hadn't touched my custom search results XSLT at all during the upgrade, so I was wondering why this number started appearing. To troubleshoot, I first edited the search results page and changed the XSLT so that I could see the Search Results XML. The XSLT looked like:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xmp><xsl:copy-of select="*"/></xmp>
</xsl:template>
</xsl:stylesheet>

This revealed to me 2 new elements right before the end of the </all_results> tag. The extra elements were 'totalresults' and 'numberofresults'.

As SharePoint 2010 now uses Federated Search Locations with custom XSLT allocated to each location, I decided to look to see what the OOB 'Local Search Results' location was doing. Turns out that it now includes a couple of extra XSLT templates:

<xsl:template match="TotalResults">
</xsl:template>
<xsl:template match="NumberOfResults">
</xsl:template>

So I added these to extra XSLT templates into my custom XSLT and voila! No more strange number at the end of my search results.

Wednesday, April 20, 2011

What to do when Content Deployment fails

I had to help out some guys from Accenture today with the setup of content deployment for a global SharePoint 2010 Internet site. Basically the first content deployment from the Authoring to Production environment didn't send across all of the published pages. As a result, settings like 'Welcome Page' were lost. Further content deployments did not seem to help or fix what was previously broken. As SharePoint's content deployment is incremental by default (UI) I created a full content deployment job through PowerShell, but then we started seeing the error 'Unable to import folder _catalogs/masterpage/Forms/Page Layout. There is already an object with the Id in the database from another site collection'.

I used my friend Google and found this, which helped me solve the problem.

So it seems that information about what has been deployed before is not contained within the Authoring environment, but the destination environment, and deleting the site collection and re-creating it with an empty template doesn't help. In my case I deleted the web application entirely and re-created it through script. In the article, you can also detach and re-attach the content database through Central Admin.