Tuesday, November 30, 2010

Image Content Type Thumbnails in 2010 Search Results

These changes will allow the SharePoint 2010 Search Results to display the thumbnail for Images stored in an Asset Library. While the thumbnails exist in SharePoint, for some reason they are not automatically displayed or easy to get to.

You can make these changes in the Search Service Application under Federated Locations/Display Information, or by modifying the Core Search Results web part in the search results.

Step 1
In the Search Service Application under Metadata Properties set up the following new managed properties, then run a full crawl

For Content Type (for some reason you cannot access the default ContentType managed Property) set up one that uses the same mappings
ContentTypeforSearch Mappings= Basic:5(Text), ows_ContentType(Text)

To get the Image File Information you'll need the URL. Despite this being mapped to something called "Thumbnail On Form" it is not the Thumbnail URL, but instead the main Image URL.
ImageFileURL Mappings= ows_ThumbnailOnForm(Text)

Step 2
After running a full crawl, add these 2 new properties to the "Columns" of the search results.

Step 3
Add the following template near the top of the XSL document, such as under the rows of xsl:param

<!-- Return the text after the last occurrence of a delimiter -->
<xsl:template name="string-find-last-text">
<xsl:param name="text" />
<xsl:param name="delim" />
<xsl:choose>
<xsl:when test="contains($text, $delim)">
<xsl:call-template name="string-find-last-text">
<xsl:with-param name="text" select="substring-after($text,$delim)" />
<xsl:with-param name="delim" select="$delim" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Step 4
Finally add a result format that will display the thumbnail image
Just above the following line:
<xsl:when test="string-length(picturethumbnailurl) &gt; 0 and contentclass[. = 'STS_ListItem_PictureLibrary']">

Add this additional xls "when" section for Images from an Asset Library (ListItem_851)

<xsl:when test="contenttypeforsearch[. = 'Image'] and contentclass[. = 'STS_ListItem_851']">

<xsl:variable name="imagefilename">
<xsl:call-template name="string-find-last-text">
<xsl:with-param name="text" select="imagefileurl" />
<xsl:with-param name="delim" select="'/'" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="imageurlroot">
<xsl:value-of select="substring-before(imagefileurl,'/')" />
</xsl:variable>
<xsl:variable name="siterootname">
<xsl:value-of select="substring-before(url,$imageurlroot)" />
</xsl:variable>
<xsl:variable name="thumbnailfilenameextension">
<xsl:text>.</xsl:text>
<xsl:call-template name="string-find-last-text">
<xsl:with-param name="text" select="$imagefilename" />
<xsl:with-param name="delim" select="'.'" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="thumbnailpath">
<xsl:value-of select="$siterootname" />
<xsl:value-of select="substring-before(imagefileurl,$imagefilename)" />
<xsl:text>_t/</xsl:text>
<xsl:value-of select="substring-before($imagefilename,$thumbnailfilenameextension)" />
<xsl:text>_</xsl:text>
<xsl:value-of select="substring-after($thumbnailfilenameextension,'.')" />
<xsl:text>.jpg</xsl:text>
</xsl:variable>


<div style=" padding-top: 2px; padding-bottom: 2px;">
<div class="srch-picture1">
<img src="/_layouts/images/imageresult_16x16.png" />
</div>
<div class="srch-picture2">
<img class="srch-picture" src="{$thumbnailpath}" alt="" /><xsl:value-of select="$thumbnailfilenameextension" />
</div>
<span><ul class="srch-picturetext">
<li class="srch-Title2 srch-Title5">
<a href="{$url}" id="{concat('CSR_',$id)}" title="{title}">
<xsl:choose>
<xsl:when test="hithighlightedproperties/HHTitle[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedproperties/HHTitle" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="title"/></xsl:otherwise>
</xsl:choose>
</a>
</li>

<li>
<xsl:if test="string-length(picturewidth) &gt; 0 and string-length(pictureheight) &gt; 0">
<xsl:value-of select="$Size" />
<xsl:value-of select="picturewidth" />
<xsl:value-of select="$Multiply" />
<xsl:value-of select="pictureheight" />

<xsl:if test="string-length(size) &gt; 0">
<xsl:if test="number(size) &gt; 0">
<xsl:text disable-output-escaping="yes">&#8195;</xsl:text>
<xsl:choose>
<xsl:when test="round(size div 1024) &lt; 1"><xsl:value-of select="size" /> Bytes</xsl:when>
<xsl:when test="round(size div (1024 *1024)) &lt; 1"><xsl:value-of select="round(size div 1024)" />KB</xsl:when>
<xsl:otherwise><xsl:value-of select="round(size div (1024 * 1024))"/>MB</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:if>
</xsl:if>

<xsl:if test="string-length(datepicturetaken) &gt; 0">
<xsl:text disable-output-escaping="yes">&#8195;</xsl:text>
<xsl:value-of select="$PictureTaken" />
<xsl:value-of select="datepicturetaken" />
</xsl:if>

<xsl:if test="string-length(author) &gt; 0">
<xsl:text disable-output-escaping="yes">&#8195;</xsl:text>
<xsl:value-of select="$Authors" />
<xsl:value-of select="author" />
</xsl:if>

<xsl:if test="string-length(write) &gt; 0">
<xsl:text disable-output-escaping="yes">&#8195;</xsl:text>
<xsl:value-of select="$Date" />
<xsl:value-of select="write" />
</xsl:if>

</li>

<li>
<span class="srch-URL2" id="{concat($currentId,'_Url')}">
<xsl:choose>
<xsl:when test="hithighlightedproperties/HHUrl[. != '']">
<xsl:call-template name="HitHighlighting">
<xsl:with-param name="hh" select="hithighlightedproperties/HHUrl" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="url"/>
</xsl:otherwise>
</xsl:choose>

</span>
</li></ul>
</span>
</div>
<div class="srch-clear">
<img alt="" src="/_layouts/images/blank.gif" />
</div>
</xsl:when>

Thursday, July 29, 2010

Picture Library vs Asset Library

SharePoint 2010 introduces the Asset Library which is similar to the Picture Library. In addition to storing pictures the Asset Library also stores video and audio. If you are trying to decide between the two for picture storage it can be fairly confusing. This post will try to capture some of the differences between the two in terms of storing pictures.
Note: So far the Asset Library is underwhelming in terms of image storage. Lack of Search support and Office integration make this library not much more than a Document Library with a custom set of Content Types. There may be more improvements on the back end for Asset Libraries, especially for video streaming, that aren't covered here.

The Picture Library does not have the ribbon toolbar. The Asset Library does. The Picture Library toolbar is one of the few places that still has a 2007 style toolbar.

Uploading Multiple Documents to a Picture Library uses Microsoft Office Picture Manager and only displays your "My Pictures" folder. You cannot navigate to other locations on your network without first adding a Picture Shortcut.
Uploading Multiple Documents to an Asset Library uses the standard Office document uploader that is the same one used in a Document Library. You can browse your entire network by default.

Selecting a picture and choosing "Send To" in a Picture Library uses the Microsoft Office Picture Manager and will let you put the image right in an Office document (PowerPoint, etc)
Selecting a picture and choosing "Send To" in an Asset Library only lets you send to another SharePoint Site or to create a Document Workspace.
Note: attempts to add the Microsoft Office Picture Manager features to an Asset Library have been unsuccessful. It will only connect to Picture Libraries

Picture Libraries have a View Slide Show option.
Asset Libraries do not have an easy way to view slide shows.

Picture Libraries have a web service at /_vti_bin/imaging.asmx that includes a number of useful operations including Download and ListPictureLibrary.
Asset Libraries cannot use this web service.

The Picture Library uses the Picture Content Type.
The Asset Library uses the Image Content Type.
These content types have similar fields.
Both have Name, Title, Preview, Keywords, Comments, Date Picture Taken, and Picture Size fields.
The Picture Content Type also has a Preview Image URL field not found in the Image Content Type.
The Image Content Type also has Author and Copyright fields not found in the Picture Content Type.
The Content Class returned for Picture Libraries in Search is STS_ListItem_PictureLibrary

Both libraries will automatically generate thumbnails of the pictures that are uploaded. Both name and store these thumbnails the same way.
Picture Library images will show the thumbnail in searches, while Asset Library images will not.
Note that I've added a blog post on how you can get the thumbnails for Asset Library images in your search results.
Digging deeper, the ows_EncodedAbsThumbnailUrl(text) field, which is mapped to the PictureThumbnailURL field that is used in search is empty for the Asset Library search results. This is likely related to the Picture Content Type having a Preview Image URL field that the Image Content Type does not have. Still, the EncodedAbsThumbnailUrl does exist as a field when browsing All Assets of the Asset Library using a CAML viewer. Oddly a field called ows_ThumbnailOnForm does exist, but contains a direct link to the file, and not to a thumbnail.
The Content Class returned for Asset Libraries in Search is STS_ListItem_851

This post will be edited as more differences emerge.

Friday, July 16, 2010

Publishing Site Missing Templates

The main Site Collection was created using the Publishing Site template. Attempting to create another Site showed only two available templates, Publishing Site and Enterprise Wiki.

To add additional templates go to Site Settings, then Page Layout and Site Template Settings. You will be able to select additional templates including the Blank Site and Team Site templates.

SharePoint 2010 Fresh Install Errors

Recently on a fresh install of SharePoint 2010 the following were observed:

Searching would give an error

Going to Search Scopes in the Site Settings would create the following error:
HTTP Error 503, The Service is Unavailable

Going to Term Store Management in Site Settings gave the following error:
The Managed Metadata Service or Connection is currently not available. The Application Pool or Managed Metadata Web Service may not have been started. Please Contact your Administrator.

Checking "Manage service applications" and "Manage services on server" both showed the Managed Metadata and Search services to be started.

Looking at the server in the Internet Information Services (IIS) Manager and clicking on the Application Pools it turned out that the "SecurityTokenServiceApplicationPool" was missing. For some unknown reason this did not install.

A wipe and fresh install was required to fix this.

Note that if the application pool does exist, make sure it is Started

Wednesday, March 31, 2010

SharePoint Designer - Data View - Filter - Query String - Show All

SharePoint Designer Data Views are a powerful way to access the information in SharePoint Lists. You have control over the XSL and can combine that with CSS and JavaScript to build some interesting tools.

One common request seems to be pulling a list, and making items in that list link to more details in another page. This can be easily handled by passing along a field in the Query String for the second page to use as a filter value. In the Data View on the second page, select Filter, Create New Parameter, then choose the Query String option.

The trouble comes in with the Default field in the Query String setting. There is no way to have the page show all list items if no Query String value is found. If you don't set a default and no Query Sting variable is passed, then you get no results from your list. If you do set a default, you only get items that work with that filter. There is no "show all" or "select *" option.

Fortunately there is a workaround. Web Part Connections can use filter values passed from another web part, but if no filter value is passed, the default is to show all of the items... basically Web Part Connections default to show all, while Filter has the opposite default of show none.

To build the workaround you need 2 Data View web parts. Build the first one with the list of all the possible variables that could be passed in your Query String. Basically this is keying off the same list that your first page did. Select the column that is being passed in the Query String (typically Title) then set up the Filter, Create New Parameter, Query String. So you've filtered this first Data View web part to show exactly the same thing that was passed in the Query String. Redundant, but necessary.

The second web part contains whatever details you wanted to show. This time use the Web Part Connections to Get Filter Values From the first web part. Now if a filter value is passed by the Query String, it will set the first web part which will then set the second. If no value is passed by Query String, the first web part will be blank, and the second will show all items.

Thursday, January 14, 2010

Adding Columns to a Custom List Form in SharePoint Designer

A previous post showed how to customize a SharePoint form using the Custom List Form. The down side to customizing your form is that if you need to add a new column to the list it will not be automatically added to the form. You must go into SharePoint Designer and edit the form code, manually adding the item back in.

The easiest route is to start by copying the code for a similar field and change the variable names to match the name of your new column.
The id number will likely start with ff and need to be unique, one greater than the current highest number. The id number appears again in the designer:bind section and the FieldDescription id. It must match in all three spots.
The column name appears in the FieldName fields and the designer:bind section. Spaces in the column name are represented by _x0020_
Verify that the field name is in the <datafields> section in the top of the web part code, just above the XSL. If not add it following the format of the existing fields.

Another option would be to delete the Custom List Form and create a new one. Assuming you've modified the Custom List Form you would need to recreate any modifications, but if they are minor that might not be difficult.

A third option would be a combo of the two above options. First make a copy of the page that the Custom List Form appears on. On that copy delete the Custom List Form and then add it back. Go into the code, copy the code you need, and paste it into the Custom List Form on the original page. When you are finished delete the copy.