MUI Refinement panel   

Tags: SharePoint 2010, Taxonomy, Search
Technorati Tags: , ,

First of all in this blog post I am going to explain how I resolved this little issue, but if this is the best solution I don’t know feel free to comment and share your idea’s with me.

 

OOB SharePoint 2010 offers a refinement panel that works great with the if you don’t use multiple languages. Unfortunately the project where I’m currently working on is a SharePoint environment with multiple languages. After some testing with search and the refinement panel I noticed that the Managed Metadata wasn’t changing when I was switching languages. This also was confirmed at the BIWUG 30/11 by Joris Poelmans.

 

After some thinking and testing I came to the conclusion that if I can edit the xml that most of my issues would be solved.

 

Here is a piece of the XML file. For getting the right term we can get the Id from the Url property.

<FilterCategory Id="Metadata_Groentenx0020_x0020Lx" ConfigId="Microsoft_Office_Server_Search_WebControls_TaxonomyFilterGenerator__-52273983" Type="Microsoft.Office.Server.Search.WebControls.TaxonomyFilterGenerator" DisplayName="Groenten - Légumes" ManagedProperty="ows_MetadataFacetInfo" ShowMoreLink="True" MoreLinkText="show more" LessLinkText="show fewer" ShowCounts="" ShowTaggingControl="false">
      <Filters>
        <Filter>
          <Value>Any Groenten - Légu…Value>
          <Tooltip>Any Groenten - LégumesTooltip>
          <Url>/Search/Pages/XMLResults.aspx?k=ui&r=Url>
          <Selection>ImpliedSelection>
          <Count>Count>
        Filter>
        <Filter>
          <Value>UiValue>
          <Url>/Search/Pages/XMLResults.aspx?k=ui&r=%22owstaxIdGroentenx0020%2Dx0020Lx%22%3D%23560159a2%2D4d98%2D4722%2Da0b1%2D1b06893769e6%3A%22Ui%22Url>
          <Selection>DeselectedSelection>
          <Count>3Count>
        Filter>
        <Filter>
          <Value>PaprikaValue>
          <Url>/Search/Pages/XMLResults.aspx?k=ui&r=%22owstaxIdGroentenx0020%2Dx0020Lx%22%3D%23e216effa%2D7bac%2D4f99%2Da762%2Dcf18ee2810bb%3A%22Paprika%22Url>
          <Selection>DeselectedSelection>
          <Count>2Count>
        Filter>
        <Filter>
          <Value>TomaatValue>
          <Url>/Search/Pages/XMLResults.aspx?k=ui&r=%22owstaxIdGroentenx0020%2Dx0020Lx%22%3D%23b4238ff9%2D6e9c%2D43d1%2Db9ad%2Dbad7317221b4%3A%22Tomaat%22Url>
          <Selection>DeselectedSelection>
          <Count>2Count>
        Filter>
      Filters>
      <MoreFilters>
        <Filter>
          <Value>AardappelenValue>
          <Url>/Search/Pages/XMLResults.aspx?k=ui&r=%22owstaxIdGroentenx0020%2Dx0020Lx%22%3D%23efad4c07%2Df37c%2D4bf5%2Da602%2Dd1ed5ff479a7%3A%22Aardappelen%22Url>
          <Selection>DeselectedSelection>
          <Count>1Count>
        Filter>
      MoreFilters>
      <CustomData>
        <AssociateTermSets>e1092ea9-35df-41fd-b790-d29c469a95a5|320d82f1-6649-43c6-96a5-8bfedeb6c9f0AssociateTermSets>
        <EscapedDisplayName>Groenten\ -\ LégumesEscapedDisplayName>
      CustomData>
    FilterCategory>

 

The following points are important to know.

  • <FilterCategory Id="Metadata_ …..    When a category starts with “Metadata_” it is metadata :)
  • The difference between “Filters” and “MoreFilters”
  • The id can be retrieved from the “Url”

 

My Fix

 

Step 1:
Create a new SharePoint Empty project and name it MUIRefinement  and choose farm solution.

image

 

Step 2:
Add the following reference Microsoft.Office.Server.Search can be found at “C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.Office.Server.Search.dll”

image

 

Step 3:
Add a new webpart NOT A VISUAL WEBPART and name it ExtendedMUIRefinementPanel

image

 

Step 4:
Add a the following usings

using Microsoft.Office.Server.Search.WebControls;
using System.Xml;
using System.Xml.Linq;
using System.Linq;

 

Step 5:
Extend the webpart to RefinementWebpart

public class ExtendedMUIRefinementPanel : RefinementWebPart

 

Step6:
Create the following extension methods. These methods converts XmlDocument To XDocument and XDocument to XmlDocument.

 public static class DocumentExtensions
    {
        public static XmlDocument ToXmlDocument(this XDocument xDocument)
        {
            var xmlDocument = new XmlDocument();
            using (var xmlReader = xDocument.CreateReader())
            {
                xmlDocument.Load(xmlReader);
            }
            return xmlDocument;
        }
 
        public static XDocument ToXDocument(this XmlDocument xmlDocument)
        {
            using (var nodeReader = new XmlNodeReader(xmlDocument))
            {
                nodeReader.MoveToContent();
                return XDocument.Load(nodeReader);
            }
        }
    }

 

Step 7:
Create a private method TranslateMetadata

private XmlDocument TranslateMetadata(XmlDocument xmlDocument)
{
    XElement element = xmlDocument.ToXDocument().Element("FilterPanel");
  
 
    var query = from p in element.Elements()
                where p.Attribute("Id").Value.StartsWith("Metadata_")
                select p;
 
    foreach (XElement item in query)
    {
        TaxonomySession sess = new TaxonomySession(SPContext.Current.Site, false);
 
        foreach (XNode node in item.Element("Filters").Nodes())
        {
            XElement cnode = (XElement)node;
 
            SetXmlValue(sess, cnode);
        }
        if (item.Element("MoreFilters") != null)
        {
            foreach (XNode node in item.Element("MoreFilters").Nodes())
            {
                XElement cnode = (XElement)node;
 
                SetXmlValue(sess, cnode);
            }
        }
    }
 
 
    return element.Document.ToXmlDocument();
}

 

First thing we do is convert XmlDocument to a XElement. The reason for this is, I think it is easier to use linq to xml for filtering certain data.

XElement element = xmlDocument.ToXDocument().Element("FilterPanel");
  

Get all the elements that starts with an id: “Metadata_”

var query = from p in element.Elements()
            where p.Attribute("Id").Value.StartsWith("Metadata_")
            select p;

 

Loop the following elements “Filters” and “MoreFilters”

foreach (XElement item in query)
{
    TaxonomySession sess = new TaxonomySession(SPContext.Current.Site, false);
 
    foreach (XNode node in item.Element("Filters").Nodes())
    {
        XElement cnode = (XElement)node;
 
        SetXmlValue(sess, cnode);
    }
    if (item.Element("MoreFilters") != null)
    {
        foreach (XNode node in item.Element("MoreFilters").Nodes())
        {
            XElement cnode = (XElement)node;
 
            SetXmlValue(sess, cnode);
        }
    }
}

 

Step 8:
Create the method SetXmlValue.

private static void SetXmlValue(TaxonomySession sess, XElement cnode)
{
    var url = Uri.UnescapeDataString(cnode.Element("Url").Value);
 
    if (url.Contains("#"))
    {
        var id = url.Substring(url.LastIndexOf("#") + 1).Split(':')[0];
 
        if (id.Length == 37)
        {
            id = id.Substring(1);
        }
 
        Term term = sess.GetTerm(new Guid(id));
 
        string result = string.Empty;
 
        result = term.GetDefaultLabel(CultureInfo.CurrentUICulture.LCID);
 
 
        if (result.Length > 14)
            cnode.Element("Value").SetValue(result.Substring(0, 13) + "...");
        else
            cnode.Element("Value").SetValue(string.IsNullOrEmpty(result) ? term.Name : result);
 
        if (cnode.Element("Tooltip") != null)
        {
            cnode.Element("Tooltip").SetValue(result);
        }
    }
}

 

First thing we need to do is get the url and unescape it so it is readable.

var url = Uri.UnescapeDataString(cnode.Element("Url").Value);

 

We will convert  /Search/Pages/XMLResults.aspx?k=ui&r=%22owstaxIdGroentenx0020%2Dx0020Lx%22%3D%23560159a2%2D4d98%2D4722%2Da0b1%2D1b06893769e6%3A%22Ui%22 to /Search/Pages/XMLResults.aspx?k=ui&r="owstaxIdGroentenx0020-x0020Lx"=#560159a2-4d98-4722-a0b1-1b06893769e6:"Ui"

 

Then we check if the url we got contains an Guid. If we look at the url we see owstaxIdGroentenx0020-x0020Lx"=#560159a2-4d98-4722-a0b1-1b06893769e6:"Ui". owstaxIdGroentenx0020-x0020Lx is the metadata property that is used to filter that certain field. #560159a2-4d98-4722-a0b1-1b06893769e6:"Ui" is the termguid with the term label(the label depends on how it is saved more about that in my previous post ).

 

Thus if the url contains “#” the url contains a termguid.

if (url.Contains("#"))
 
To get the id we have to know that the last id we find is the id we are going to filter.
 
var id = url.Substring(url.LastIndexOf("#") + 1).Split(':')[0];
 
if (id.Length == 37)
{
    id = id.Substring(1);
}

 

We have to check the length of the id. sometimes the XML return the property Metadata_Tags. In the Metadata_Tags there will be an extra 0 in the id. e.g. “0560159a2-4d98-4722-a0b1-1b06893769e6”

 

When we have the id, we can get the term label in the current language.

Term term = sess.GetTerm(new Guid(id));
 
string result = string.Empty;
 
result = term.GetDefaultLabel(CultureInfo.CurrentUICulture.LCID);
 
For branding reasons if have chosen to limit the length of the of the term to display. After we get the result we can now change the value of the Value property with the term label.
if (result.Length > 14)
    cnode.Element("Value").SetValue(result.Substring(0, 13) + "...");
else
    cnode.Element("Value").SetValue(string.IsNullOrEmpty(result) ? term.Name : result);
 
if (cnode.Element("Tooltip") != null)
    cnode.Element("Tooltip").SetValue(result);

 

Step 9:
Create a global property.

private RefinementManager _manager;

 

Step 10:
Override the onit method to set the refinementmanager

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
 
    //get the refinementManager
    _manager = RefinementManager.GetInstance(this.Page, this.QueryNumber);
}

 

Step 11:
Override the GetXPathNavigator to send the altered XML to the refinementpanel.

 
protected override XPathNavigator GetXPathNavigator(string viewPath)
{
    XmlDocument xmlDocument = _manager.GetRefinementXml();
 
    if (xmlDocument == null)
            return base.GetXPathNavigator(viewPath);
            
    xmlDocument = TransLateMetadata(xmlDocument);
 
    return xmlDocument.CreateNavigator();
}

 

Step 12:
Build and deploy your solution.

 

Result

Refinementpanel in Dutch

image

Refinementpanel in French

image

 
Posted by  Gilissen Timmy  on  12/13/2011
12  Comments  |  Trackback Url  | 0  Links to this post | Bookmark this post with:        
 

Links to this post

Comments


Timmy  commented on  Tuesday, December 13, 2011  11:20 AM 
You can download the wsp at our codeplex site.

http://ventigrate.codeplex.com/releases/view/78674


  commented on  Tuesday, January 24, 2012  2:07 PM 
Thanks for the great info dog I owe you bggitiy.


qfzrmjxkqt  commented on  Wednesday, January 25, 2012  9:44 AM 
SlNRGP blvnugbdyyei


wehwcsbgokl  commented on  Thursday, January 26, 2012  9:56 AM 
cm5k2u , [url=http://ctyogmrccpaz.com/]ctyogmrccpaz[/url], [link=http://dpqxnhpxduhk.com/]dpqxnhpxduhk[/link], http://ukjxnmlrpkva.com/


evanruede  commented on  Friday, January 27, 2012  12:49 PM 
ultram cheap tramadol uvox toradol >:-OOO synthroid pefq


lamassaymoo  commented on  Tuesday, January 31, 2012  9:40 AM 
accutane online pharmacy 689 synthroid for sale kkzhix tramadol 889042


green4dude  commented on  Friday, February 17, 2012  2:44 AM 
Just noticed today, some of the keyword via search engine has SER position noted at the end. Awesome. That is a great SEO function. Statcounter just nailed it with that thing.



hannsock  commented on  Sunday, February 19, 2012  2:47 AM 
Alias is useful only if you're dealing with complex queries involving multiple tables; specially if you run the risk of 2 different tables having the same or similar field names.



lambarii  commented on  Tuesday, February 21, 2012  2:37 AM 
I wouldn't be able to get rid of it either! I'm not much of a collector, but when it comes to sentimental items, it's impossible for me to part with them. xo



akgcandlefish  commented on  Friday, February 24, 2012  3:04 AM 
Paki, aunque con retraso, te comunico que todos los que lo solicist teis a trav s de los coemntarios est is admitidos/as



qeanut  commented on  Saturday, February 25, 2012  2:48 AM 
Paki, aunque con retraso, te comunico que todos los que lo solicist teis a trav s de los coemntarios est is admitidos/as



SassieGRule  commented on  Sunday, February 26, 2012  3:03 AM 
Paki, aunque con retraso, te comunico que todos los que lo solicist teis a trav s de los coemntarios est is admitidos/as


Name *:
URL:
Email:
Comments:


CAPTCHA Image Validation