Category: Development

SharePoint or Application Development related posts

Azure Table Storage Primer

As companies continue to move to the cloud we are constantly finding new and better way to meeting requirements and deliver rock solid solutions.  Over the last year there is one area where my team has found some great capabilities that I believe are currently under utilized by SharePoint and Office 365 developers, and that is Azure Table Storage.  For those that are not familiar with it, Azure Table storage is a service within the Azure Storage group that stores structured NoSQL data.  It is incredibly fast, inexpensive, and NoSQL gives you the capability to store content with flexible datasets.  We have started to rely on this for both internal products as well as client consulting engagements.  Thanks to the technical leadership and innovation from Jake Dan Attis we have started to find a number of creative uses for the service, some of those solutions I’ll be blogging about over the next few months.

In the meantime, here is a good primer for Azure Storage:

Along with some great links for working with Azure Table Storage:

 

 

 

 

Search Results in Grid View

A pretty common request I get when working with Search results for content solutions is to display the results as a grid, and not the normal block format we see with the standard search results below. 

Since we have full control over how things are rendered with the display templates, it is pretty easy to alter the formatting now using simple html and javascript to render it as a grid. 

For this example, we are going to assume that the grid format will be applied to all items uniformly.  To do that, we will select a specific display template to use instead of allowing the rules to detect the appropriate template, item by item.  For this example, I’m going to work with a copy of the Item_OfficeDocument.html display template which has the following markup:

_#=ctx.RenderBody(ctx)=#_

The ctx.RenderBody(ctx) line will inject the standard rendered output. You can really structure this with whatever markup suits your requirements. When I need to provide a grid or tabular format I will typically use an unordered list that floats. Here is a simple three column example:

        
  • _#=ctx.CurrentItem.Title =#_
  • _#=ctx.CurrentItem.DisplayAuthor=#_
  • _#=formattedDate=#_

In this example, you may notice that I also did some formatting the UTC formatted date. This is a good example of how we can manipulate the data as needed.  Below is an example of the grid view.

 

 

While this is a simple example that uses only default fields available to all lists and libraries, it is easy to add in additional properties that can be leveraged by your markup. The only real stipulation here is that you will need to make sure that it is a property recognized by the search index. At the top of the document there is property called "ManagedPropertyMapping" which lists the properties that need to be loaded and available for the markup. Here is the default value for the Item_OfficeDOcument template.

'Title':'Title','Path':'Path','Description':'Description','EditorOWSUSER':'EditorOWSUSER','LastModifiedTime':'LastModifiedTime','CollapsingStatus':'CollapsingStatus','DocId':'DocId','HitHighlightedSummary':'HitHighlightedSummary','HitHighlightedProperties':'HitHighlightedProperties','FileExtension':'FileExtension','ViewsLifeTime':'ViewsLifeTime','ParentLink':'ParentLink','FileType':'FileType','IsContainer':'IsContainer','SecondaryFileExtension':'SecondaryFileExtension','DisplayAuthor':'DisplayAuthor','ServerRedirectedURL':'ServerRedirectedURL' 

To add in a custom property, you simply need to add in the name/value pair. For example:

'Title':'Title','Path':'Path','Description':'Description','EditorOWSUSER':'EditorOWSUSER','LastModifiedTime':'LastModifiedTime','CollapsingStatus':'CollapsingStatus','DocId':'DocId','HitHighlightedSummary':'HitHighlightedSummary','HitHighlightedProperties':'HitHighlightedProperties','FileExtension':'FileExtension','ViewsLifeTime':'ViewsLifeTime','ParentLink':'ParentLink','FileType':'FileType','IsContainer':'IsContainer','SecondaryFileExtension':'SecondaryFileExtension','DisplayAuthor':'DisplayAuthor','ServerRedirectedURL':'ServerRedirectedURL', 'MyProperty':'MyProperty'

Leveraging Search Web Parts and Display Templates

One of my main focuses the past 4-5 years has been leveraging the Search Infrastructure to help deliver dynamic content to portals and Intranets.  In previous versions of SharePoint I leaned heavily on the underlying APIs to deliver custom solutions.  This was both because the underlying APIs allowed more precise querying and because it gave me full control on what was rendered to the user.

With SharePoint 2013 the Search related web parts went through a pretty major renovation, especially for on-premises customers that have Enterprise CALs.  A series of web parts were created, with a full featured query builder that allows you to create and test your queries through a web interface.  Where the results were previously rendered in XSLT, the new method utilizes regular html and javascript to create the output markup which is then injected into the page.  The overall rendering of the pages is much more dynamic, with support to display each item differently based on the type of content it is.  The potential is limitless. 

I intend for this post to be a bit of a primer on the high level topics.  I’ll be coming out with some specific task-driven follow up posts over the next few weeks that expand on these concepts and get into some examples of things that can be done through these new features. 

Dynamic Content using Search Web Parts

For those that haven’t caught my session Dynamic Content using SharePoint Search here is a brief overview.

The web parts themselves are broken into the following categories:

  • Content Rollup (Enterprise Feature)
  • Search-Driven Content (Enterprise Feature)
  • Search

 

Within the Content Rollup category resides the Content Search web part.  This is a great replacement for the Content Query Web Part (CQWP) available in past versions of SharePoint.  Unlike the CQWP, this utilizes the search service so it can pull matching results from anywhere in your farm, which means you are not limited to the current site collection. 

The web part also supports new, previously unavailable display options including the ability to show the item as a slideshow. 

The Search-Driven Content category contains a series of web parts that are all based on the Content Search web part, with a pre-set query to help you get started.  This includes results that display specific types of content like the Videos, Web Pages, Wiki Pages, Pictures, Pages, and then also results that rely on the analytics features to deliver results pertaining to Popular Items, Recently Changed Items, and Recommended Items.  The pre-configured queries are a great start, and using the query builder form you can dial in the specific results you are looking to display. 

Search Display Templates

All of the search web parts, including the standard Search Results web part that is available in all versions of SharePoint Server as well as the SharePoint Online service within Office 365, then offer the ability to change how your results are rendered using the Search Display Templates.  This is where the real power of the new changes come into play since we can now change how items are rendered by editing the html and javascript in the display templates. 

The display templates are stored in the Master Page Gallery for each site collection.  You can find them by browsing to Site Settings, and clicking the Master pages and page layouts link under the Web Designer Galleries group.  From within the gallery, browse into the display templates directory, and then into the Search directory for search specific display templates. 

A good reference for the included display templates is available here on the TechNet/MSDN website:  http://technet.microsoft.com/en-us/library/jj944947(v=office.15).aspx

Here is a good overview of how to work with the display templates:  http://msdn.microsoft.com/en-us/library/office/jj945138(v=office.15).aspx

SPSEvents NYC and Social API Presentation

I’m excited to announce that my session Introduction to SharePoint’s Social APIs has been selected for the SPS Events NYC event on Saturday July 27th.  This has been a fantastic event the past few years, and I’m sure this year will be no different. 

Here is the abstract for my session:

SharePoint 2010 and 2013 offers a rich set of social capabilities that are built into the platform.  Those capabilities are available to developers through a variety of APIs so that they can be extended or leveraged in your other customizations and applications.  This session will run through the various client, server, and REST APIs available to developers.

 

We will take a close look at the APIs themselves, work through a couple of common and not so common example of leveraging those APIs, and then talk about things like performance and best practices.

If you are in the area, stop by and say hello!

Finding Duplicate Items and The Duplicates Keyword

I have had a few questions around de-duping files within a SharePoint environment recently so I set off to do some research to identify a good solution.  Based on past experiences I knew that SharePoint identifies duplicates while performing an index of the content so I expected this would be part of the solution.

Upon starting my journey, I found a couple of threads on various forums where the question has been asked in the past.  The first one was “Good De-Dup tools for SharePoint” which had a link to a blog post by Gary Lapointe that offered a PowerShell script that can list every library item in a farm.  At first glance this seemed to be neat, but not helpful here.

Next I found a blog post with another handy PowerShell script.  This blog post was title Finding Duplicate Documents in SharePoint using PowerShell.  I found this script interesting, albeit dangerous.  It will iterate through all of your site collections, sites, and libraries, hash each document and compare for duplicates.  It however only identifies duplicate documents within the same location.  The overhead of running this script is going to be pretty high, and it gets a little risky when you have larger content stores.  I would be worried about running this against an environment that has 100s of sites, or large numbers of documents.

Next I found an old MSDN thread named Find duplicate files which had two interesting answers.  The first was to query the database (very bad idea) and the second was a response by Paul Galvin that pointed to the duplicates keyword property, and a suggestion to execute a series of alpha wildcard searches with the duplicates keyword.  While I have used the duplicates keyword before I had never thought to use it in this context so I set out to give it a try.

As I mentioned at the beginning SharePoint Search does identify duplicates documents.   It does this by generating a hash of the document.  Unlike the option above where the PowerShell generates a hash, the search hash seems to separate out the meta-data so even items with unique locations, meta-data, and document names can still be identified as identical documents. 

When doing some tests though I quickly discovered that the duplicates property requires the full document URL.  This means that you would have to execute a recursive search.  First you would have to get a list of items to work with, and then you would then need to iterate through each of those items and execute the duplicates search with a query such as duplicates:”[full document url]”.

Conceptually there are two paths forward at this point.  The first is to try and obtain a list of all items from SharePoint Search.  Unfortunately you cannot get a full list of everything.  The best you can do is the lose title search that Paul had suggested.  Something like title:”a*” which would return all items with an a in the title.  You would then have to go through and do that for all letters and numbers.  One extra challenge is that you will be repeatedly processing the same items unless you are using FAST Query Language and have access to the starts-with operator and can do something like title:starts-with(“a”).  In addition, since we are only looking for documents, its an extremely good idea to also add in the isdocument:true to your query to ensure that only documents are returned.  Overall this is a very inefficient process.

An alternative would be to revisit and extend Gary’s original script to execute the duplicates search for each item.  The advantage here is that you would guarantee that you are only executing the duplicates search once for each item which would reduce the total processing and extra output information to be parsed.  The other change to Gary’s script would be to change what is written out to the log file since you would only write out the information for items that are identified as duplicates. 

SharePoint Saturday New York–Wrap-up

The SharePoint Saturday NY event was a huge success.  Great to see so many people show up and engaged in discussions.  The organizers and volunteers did a great job this year to make sure the event went off without a hitch.  Very well orchestrated!

Thank you to everyone that attended my session.  I hope you enjoyed it and found it useful in building your development skills around search and FAST Query Language. 

 

The source code is available here.

Congratulations to the winners of the give away for copies of my book SharePoint 2010 Business Application Blueprints

%d bloggers like this: