-->

Tuesday, 27 March 2012

Add Rating Stars to the Search Results

I Hope you found my previous article on Encoding and Decoding Refiner Values useful. In this article I will Explain to how to Add Rating Stars to the search results. Please let me know if you find any issues while implementing it.

Create a Custom List and Enable Rating on it

We will start with creating the list with some dummy columns and insert some data in it. I have created a 'Employee List' whose structure looks something like this

Now we need to enable the rating to the list. Click on the list settings from the ribbon under the 'List Tools' Group and 'List' tab
Now click on the 'Rating Settings' link under the 'General Settings' category.
Select 'Yes' under 'Allow items in this list to be rated?' and click 'Ok'.

This has successfully enabled ratings on the list and added following two columns required for rating to work.

Rating (0-5)   Rating (0-5)  
Number of Ratings   Number of Ratings 

If you go back to the list it would have added the Rating Column to the list.


Rate some Entries in the List and Run the Services for Rating

Now add rating to these entries. It wont be reflected immediately on the list, it will get updated once 'User Profile Service Application - Social Data Maintenance Job' and  
'User Profile Service Application - Social Rating Synchronization Job' jobs are executed.


This jobs are scheduled to run every hour (By default) by the sharepoint timer services. However we can change the frequency of the this jobs

Go to Central Administration -> Monitoring -> Timer Jobs -> Review job definitions

Scroll down to locate the above services


Click on each of the job and schedule it to run for every 1 min (Just so that we don't have to wait for our ratings to get updated, in normal scenario running every 

one hour is just fine !)

Once this jobs are executed successfully, the ratings that you entered previously would have started reflecting.


Start the Full Crawl of the site to Create Crawl Property


Now once we have to prepare our FAST search server to include the ratings in our search indexing.

So go to the crawled property categories and select 'Sharepoint' category. Now search for 'rating'

It should return following to crawled properties

ows_averagerating(Decimal)
ows_ratingcount(Integer)


If it does not return the above two crawled properties, You need to start full crawl of the site where your list is located.
Once the crawl is successfull, sharepoint will automatically create the above crawled properties

Create Managed Property for the Ratings


As we have the crawled property created we can create a managed property for each of them and map it to crawled property.

So you need to create following two managed property
a. Rating
b. RatingCount

Below are the details of the managed property that will help you to create a managed property.



Start the full crawl of the Site

After creating the managed property we need to full crawl the site 'AGAIN'. Yes, When we earlier crawled the site it just recognised that two more fields are available for crawling. But managed properties were not mapped so it didnt knew where to index the data.

so start the full crawl of the site, leave it as it is and proceed to the next step.

Modify Core Result Webpart and it's XSLT

Now we need to modify the search webpart of our site to display the rating stars in our search.

So go to your results.aspx and then edit the page. Now edit your core results webpart.

Under coreresultswebpart properties->Core Result -> Display Properties -> Fethced Properties
A. Include the following lines before the </Column> tag

<Column Name="Rating"/>
<Column Name="RatingCount"/>

B. Open the XSL Editor of the webpart by clicking on 'XSL Editor' button

Add the below lines of code after the Div tag of '<div class="srch-Title2">'

  <div class="srch-Description">
    <xsl:if test="rating &gt; 0">
      <b>
        <xsl:call-template name="DisplayRating">
          <xsl:with-param name="theRating" select="rating" />
          <xsl:with-param name="theRatingCount" select="ratingcount" />
        </xsl:call-template>
      </b>
      <br />
    </xsl:if>
  </div>

C. Copy the following code before the </xsl:stylesheet> tag

<xsl:template name="DisplayRating">
  <xsl:param name="theRating"/>
  <xsl:param name="theRatingCount"/>
  <xsl:if test="$theRating > 0">
    <div style="display: inline-block; padding-left: 8px;">
      <div>
        <xsl:variable name="tempTitle" select="concat($theRating, ' Stars (')"/>
        <xsl:variable name="tempTitle2" select="concat($theRatingCount, ' Ratings)')"/>
        <xsl:variable name="ratingTitle" select="concat($tempTitle, $tempTitle2)"/>

        <xsl:attribute name="title">
          <xsl:value-of select="$ratingTitle"/>
        </xsl:attribute>
        <xsl:choose>
          <xsl:when test="round($theRating) = 0 and $theRating &gt; 0">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-368px 0px;width:16px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 1 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-352px 0px;width:16px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 2 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-352px 0px;width:32px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 2 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-336px 0px;width:32px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 3 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-336px 0px;width:48px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 3 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-320px 0px;width:48px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 4 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-320px 0px;width:62px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 4 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-304px 0px;width:64px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 5 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-304px 0px;width:80px;</xsl:attribute>
          </xsl:when>
          <xsl:when test="round($theRating) = 5">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-160px 0px;width:80px;</xsl:attribute>
          </xsl:when>
        </xsl:choose>
      </div>
    </div>
  </xsl:if>
</xsl:template>




Click 'Ok' and save the page.

Search Results

You are ready to search for the results now ! My search page something like this 



So this brings to end of this post.

Thank you.. Have a nice day !
Happy Sharepointing !

Wednesday, 21 March 2012

Encode and Decode Refiner value from the Query URL

I hope you liked my previous post on "Adding Filter in the Refinement Panel of the Search Page". I was exploring more about how the Refinement works and I found out then whenever we hover over each filter on the refiner it shows the url value to be encoded.


Something like this,
https://search.com/pages/peopleresults.aspx?k=*&r=dttsource%3D%22AQpVUzpEU3RyZWV0CWR0dHNvdXJjZQEBIgEi%22


if we decode the above url, we will get something like this
https://search.com/pages/peopleresults.aspx?k=*&r=dttsource="AQpVUzpEU3RyZWV0CWR0dHNvdXJjZQEBIgEi"

k=* specifies that i have performed the Keyword search for "*", i.e wildcard search
r=dttsource="AQpVUzpEU3RyZWV0CWR0dHNvdXJjZQEBIgEi" specifies that the list of fiters we have applied

Here i cannot know which filter I actually applied. Also it was difficult to understand how the refinement panel constructs the query string by combination of the multiple filters.
But it's very important for me to know which filter I applied, So i developed a small utility which will encode as well as decode the refiner value.

Decode Refiner Value from Query URL


Encode the Refiner Value from the filter name and column value


You can download both the utility from here

Note: For some OS/Browsers you might have to rename the files to .exe extension

I hope this post and utility was useful to you.

Thank you. Happy Sharepointing !

Friday, 17 February 2012

FAST Search Server not Configured to the Sharepoint 2010

When I was configuring the FAST search server on my SharePoint, it got configured successfully as a standalone type. But when I tried to create the Search Service Application, to my surprise, the options to create a "FAST Search Connector" and "FAST Search Query" were missing. After Googling a bit, I realized that FAST search was installed but it was not connected to the existing SharePoint server. Even though the Sharepoint Farm properties were correctly configured during FAST installation.

After a little while I realized that License that i have was for the SharePoint Standard, and this features are included in the SharePoint Enterprise. So I was thinking to install the SharePoint again, But luckily there is an option to change your SharePoint license type from SharePoint Standard to SharePoint Enterprise.

  • Go to Central Administration -> Upgrade and Migration  and click on Enable Enterprise Features.
  • Select the radio button for the Enterprise and it will ask for the license key.(Make sure you have the license key for the SharePoint Server Enterprise)
  • Type in the Key and click OK. It will enable all the enterprise features on your SharePoint farm.

If you have new SharePoint farm then you can alternatively re install the SharePoint 2010 with the license key for the SharePoint Server Enterprise. This is pretty important screen :)
FAST Search Server not Configured to the Sharepoint 2010

Complete your installation with the SharePoint Server Enterprise license key and after the successful configuration of the FAST you will be able to see the options of the FAST Search Connector and FAST Search Query while creating a new Search Service Application.

FAST Search Server not Configured to the Sharepoint 2010

The FAST Search Service Application types are not available in a "Basic" installation.  This limitation is specific to the Beta and is planned to be removed for the final release. More information on this link.

Friday, 10 February 2012

Troubleshooting Crawl Issues for SSL Enabled Web Application

Lately I have experienced lot of issues while crawling of SSL enabled web application and wasted almost 2-3 days fixing it. So thought to share the troubleshooting steps on my blog.

Issue 1 : Ignore SSL Warnings

Error message: An unrecognized HTTP status was received. Check that the address can be accessed using Internet Explorer. (WebExceptionStatus TrustFailure The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
This happens mostly when we implement self signed certs or certs from untrusted authorities in the web servers. In order to avoid the error message and to successfully crawl contents, make  the following changes in farm level search settings in Central Administration.
  1. Go to Application Management > Search Service Application Settings > Farm Search Administration
  2. Change the setting “Ignore SSL warnings” from No to Yes
Issue 2 : Install the FAST search Certificate
The URL of the item could not be resolved. The repository might be unavailable, or the crawler proxy settings are not configured. To configure the crawler proxy settings, use Search Administration page.
Install the certificate using the following command on the Sharepoint Admin Server
.\SecureFASTSearchConnector.ps1 –certPath FASTSearchCert.pfx –ssaName “FAST Connector” –username "domain/username"

Note : The FASTSearchCert.pfx is created when you install the FAST on the server. You can locate it under <FASTSEARCH>\Data\Data_Security\cert folder. Also on the execution of the command it will ask for the certificate password, It is the password that you entered while configuring the FAST on the server.

Issue 3 : Collection not created
Failed to connect to ame.fantasia.qa:13391,ame.fantasia.qa:13391 Failed to create session with content distributor. Unknown collection 'MyCollectionTest'
This happens when collection specified the SSA is not present in the FAST database. To check if your collection exist you can execute the following command on the FAST server. 
                 Get-FASTSearchContentCollection -Name MyCollectionTest
or else you can create a new collection with the following command 
                  New-FASTSearchContentCollection -Name MyCollectionTest
For me it was not present hence gave me an error. For quick fix, i changed the collection name back to sp. Its the default collection and was already present.

Issue 4 : Access Denied to the Default Content Access Account

Access is denied. Verify that either the Default Content Access Account has access to this repository, or add a crawl rule to crawl this repository. If the repository being crawled is a SharePoint repository, verify that the account you are using has "Full Read" permissions on the SharePoint Web Application being crawled. 
This happens when the content access account does not have "Full Read" permissions on the Sharepoint web application being crawled. You can add a crawl rule to access the repository with specific account.
  1. Go to New Crawl Rule -> add the Url 
  2. Check the radio button for 
  3. Click Ok and start the crawl.
Also make sure there is an entry for DisableLoopbackCheck in the registry. 
If its not present follow the below steps :
  1. Go to command window and type regedit.exe
  2. Navigate to  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
  3. Right click on LSA and create a new 32bit DWORD value
  4. Name it as "DisableLoopBackCheck" and modify its value to 1
  5. Close the registry and crawl the content.
 Issue 5 : Error communicating to the server
The crawler could not communicated with the server. Check that the server is available and that the firewall access is configured correctly. If the repository was temporarily unavailable, an incremental crawl will fix this error.
This happens when crawler is not able to connect to the server. Make sure server name is correct. Couple of steps to troubleshoot it
  1. You should be able to ping the server from the server having crawl component. Make sure there is an entry for the server in the host file under c:\Windows\System32\drivers\etc folder.
     Ping <servername>
  2. You should be able to connect to the server using telnet command
    Telnet <servername> <port number>


Adding Filter in the Refinement Panel of the Search Page



Following are the steps to add a refinement in the refinement panel of the sharepoint page.


Extract XML of the Filter Category Definition
we need to extract the xml of the Filter Category Definition from the existing default refinement panel.

A. In your browser, navigate to the results page URL:
       http://SiteURL/Pages/results.aspx
B. On the Site Actions menu, click Edit Page.
C. In the Refinement Panel Web Part, click the edit arrow to display the Web Part menu, and then click Edit Web Part. This opens the Web Part tool pane.
D. In the Refinement section, clear the Use Default Configuration check box.
Adding Filter in the Refinement Panel of the Search Page
E.  In the Refinement section, click the ellipsis (…) button for the Filter Category Definition field.
This opens the Text Entry window for the Refinement Web Part's FilterCategoriesDefinition property. You can modify the XML directly in this window; however, you may find it easier to copy the code to a file.
Adding Filter in the Refinement Panel of the Search Page


Edit the XML in Visual Studio    
Now we need to edit the given xml in visual studio preferably. You will find a filters already present for the Result Type, Site, Author,etc by default. We will try to add our own filter in it.
We will add ‘Content Source’ category filter to it, so that we can filter based on the content source from which the result was crawled.
Scroll to the end of the xml and add the following line before </FilterCategories> tag

<Category    Title="Content Source"    Description="Use this filter to restrict results authored by a specific content source"    Type="Microsoft.Office.Server.Search.WebControls.ManagedPropertyFilterGenerator"    MetadataThreshold="1"    NumberOfFiltersToDisplay="4"    MaxNumberOfFilters="20"    ShowMoreLink="True"    MappedProperty="contentsource" SortBy="Frequency"    SortDirection="Descending"    SortByForMoreFilters="Name"    SortDirectionForMoreFilters="Ascending"   MoreLinkText="show more"    LessLinkText="show fewer"    ShowCounts="Count" />


Save back the edited XMl of FilterCategoriesDefinition in webpart
Copy back the edited xml to the webpart’s FilterCategoriesDefinition property and click ok. Now our webpart is ready to use content source as a filter. But main catch here is that content source property is not retrieved in the ContentCoreResult Webpart without which our filter will be of no use.


Add the column for Content Source
Add the column for “Content Source” in the ContentCoreResult webpart
A.In your browser, navigate to the results page URL:
http://SiteURL/Pages/results.aspx
B. On the Site Actions menu, click Edit Page.
C. In the Content Core Result Web Part, click the edit arrow to display the Web Part menu, and then click Edit Web Part. This opens the Web Part tool pane.
D. In the Core Results->Display Properties section, clear the Use Default Configuration check box.
E. In the Display Properties section, Copy the fetched Properties in visual studio editor
F.  Now add the following line at the end of the document before </Columns> tag and save the webpart properties

<Column Name="contentsource"/>

 Make sure there is an entry for the managed property content source mapped to the crawled property Content Source


Adding Filter in the Refinement Panel of the Search Page

Result
    
Now go to the search site and search for the result, you will be able to see new filter added  to the refinement panel 


                      Adding Filter in the Refinement Panel of the Search Page
                 

Wednesday, 18 January 2012

Customizing CoreResultWebpart in FAST Search Center

Create an empty sharepoint project
Create an empty Sharepoint Project and name it as a 'MyCustomCoreResult'
Customizing CoreResultWebpart in FAST Search Center

Click Ok and then enter the url of the sharepoit fast search site
Customizing CoreResultWebpart in FAST Search Center 


Add Custom Core Results Webpart in the project (inherit from CoreResultsWebpart)
Now right click on the project and click on add -> 'New item' ->  Webpart
Customizing CoreResultWebpart in FAST Search Center

Enter the name of webpart as MyCustomCoreResultWebpart and click on Add button

If you look at the Code behind file of the webpart i.e. MyCustomCoreResultWebpart.cs, by default it would be inherited from the Webpart class replace it with the CoreResultsWebPart class.

Note : You might have to add the Microsoft.Office.Server.Search.dll most likely located under C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.Office.Server.Search.dll

Overriding the methods
You need to override following 3 methods
a.       CreateChildControls
protected override void CreateChildControls()
{
  base.CreateChildControls();
}

b.      OnInit
protected override void OnInit(EventArgs e)
{
 base.OnInit(e);
}
c.       ChangeDataSourceProperties
protected override void ConfigureDataSourceProperties()
{
  base.ConfigureDataSourceProperties();
  this.XslLink = "/_layouts/xsl/MyCustomCoreResultsXSLT.xslt";
}

Add a SharePoint Mapped Folder

Now we need to add our custom XSLT file to the sharepoint site. Right click on the project and click on Add-&gt;Sharepoint Mapped Folder.
Customizing CoreResultWebpart in FAST Search Center


Now select the appropriate folder for you custom XSLT to reside. For our example I have selected the XSL folder under {SharepointRoot} -&gt; Template -&gt; Layouts -&gt; XSL folder. Click on Ok and it will map the sharepoint XSL folder to our project.

Add CustomCoreResult.xslt file
Now we need to get the default xslt of the coreresultwebpart. You can get it from here
Get the content of the xslt from the above link and paste it in this file. You can customize the look and feel of the webpart using this xslt. For this example we will just highlight the matched string of the userquery with orange color.
Search for the string “c0” in the file, You will find something like this

<xsl:template match="c0">
    <b>
      <xsl:value-of select="."/>
    <b>
</xsl:template>


Replace the above section with the following one.

<xsl:template match="c0">
    <span style="background-color:orange">
      <b>
        <xsl:value-of select="."/&gt;
      </b>
    </span>
</xsl:template>
    
    Build and Deploy Project
This will automatically deploy the webpart and feature in the site you selected earlier. By default feature will be activated. In case it’s not activated, you might have to activate it manually.
     Open the site and edit the Results.aspx page to replace the default coreresults webpart with our custom webpart from the custom category in webpart gallery.
      Save the page and now the results.aspx should be using your webpart.
Customizing CoreResultWebpart in FAST Search Center




As you can see now the highlighted matches will appear in orange color. Some of the other things that you can try is adding new columns in the display results. I have added the Site Name, Company, Content Source details in the search results.


Thursday, 12 January 2012

Get XML data from the CoreResultsWebPart

We often want to debug the XSLT code that we have written for our CoreResultsWebPart, this post will help you to extract the data from the CoreResultsWebPart and later which we can apply to debug our custom XSLT written for the CoreResultsWebPart.

Prerequisites

1. You need to have the Administrator privileges
2. Basic understanding of creating web applications and running the FAST search.

TODO

First thing you need to do is get the Basic Fast Search Center site up and running. Below i have mentioned the brief steps.
1. Create Web application with classic mode authentication.
2. Create a root site collection with "Fast Search Center" template.
3. Open the root site collection and try to search, as long as it displays the result you are fine :)

First Step : Edit the page and replace the default XSL with our custom XSL

As you Site is up and running, search for any term and go to the results page. Edit the page from Site Actions -> Edit Page
Search for the Search Core Results web part on the page and edit the web part. In the search core results editor pane, go to the Core Results->Display properties.

Uncheck the "Use Location Visualization" option, by default it would be checked.
Note: It means that site has to use the columns and XSL defined at the federated location level. Which is shared by all the search sites in the farm. When we uncheck this option we can define our own XSL format. More information on this topic can be found here
 
On unchecking this option the area under Fetched Properties and XSL editor will be enabled.
Fetched Properties are the columns that you want to be retrieved from the FAST search database. The columns mentioned within these properties will only be fetched.

Now click on the XSL editor button, it will open the dialog displaying the XSL used for the CoreResultsWebpart. Replace the default XSLT with the following code. Don't forget to take the backup of default code in case you want to revert back to original code :)

<?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="/">
<xsl:copy-of select="*"/>
</xsl:template>
</xsl:stylesheet>

 Click on Ok and save the page. 

Second Step : View the Search Results Web part XML data

Right-click the page zone that contains the Search Results Web Part that you want to view the search results XML data for, and then click View Source on the pop-up menu. This opens a page in Notepad that contains the HTML source. 


Search for the string “<All_Results>”. This is the opening tag for the section that contains the full search results set for the Web Part you modified.