Posts Tagged ‘SharePoint 2010’
Cinto
Branche: ICT & Internet dienstverlening
Februari 2011 – april 2011
SharePoint developer
Voor Cinto heeft Anita advies uitgebracht welke webparts interessant kunnen zijn voor de een beschikbaar te stellen SharePoint 2010 omgeving aan klanten. Naar aanleiding van dit advies is er samen met Cinto een besluit genomen welke webparts aansluiten bij de doelgroep. Deze webparts heeft Anita ontwikkeld.
De gewenste vormgeving wordt toegepast middels het plaatsen en activeren van een ontwikkeld theme. Buiten het theme wordt een aanvullend css bestand toegepast.
Deze functionaliteit is samengebracht in een SharePoint 2010 webtemplate. Op deze manier zijn sites op een eenvoudige en eenduidige manier aan te maken.
SharePoint Foundation 2010, Visual Studio 2010
Imtech
Branche: ICT & Internet dienstverlening
Februari 2011 – mei 2011
Lead developer SharePoint
Oasen maakt drinkwater voor 750.000 mensen en 7.200 bedrijven in het oosten van Zuid-Holland. Het voorzieningsgebied bestaat uit 32 gemeenten.
Op dit moment is de publieke website van Oasen gebaseerd op MOSS2007. Door een nieuwe visie op de vindbaarheid van content, indeling, interactie met de klant en dynamiek is er een nieuwe website ontwikkeld op basis van SharePoint 2010. Een derde partij heeft de ontwikkeling van het design op zich genomen. Het team van Imtech aangevuld met Anita mag de website ontwikkelen op basis van het User Experience document wat het design laat zien.
Basis voor de technische oplossing voor de nieuwe website zijn het User Experience document en de website van Oasen. De technische oplossing en implementatie van de nieuwe website zijn bepaald door het projectteam. Anita is verantwoordelijk voor deze technische keuzes en oplossingen.
Het projectteam bestaat uit een projectleider, consultant, lead engineer, twee engineers en drie designers. Anita vervult de rol van lead engineer. Scrum wordt toegepast met sprints van 2 a 3 weken. De totale doorlooptijd van het project is 9 weken.
Er wordt waar mogelijk gebruik gemaakt van standaard SharePoint componenten, welke aangepast en uitgebreid worden om de exact gewenste functionaliteit te verkrijgen.
De nieuwe website van Oasen maakt zeer intensief gebruik van de SharePoint Search functionaliteit. Dit is de technische basis en komt in vele onderdelen van de website terug. Content in de website wordt voorzien van metadata (onder andere tags) om de vindbaarheid te verbeteren en om de content te kunnen verfijnen op basis van deze tags. De content is onderverdeeld in verschillende types als nieuws, artikelen, applicaties, veelgestelde vragen, foto’s, video’s en storingen.
De traditionele navigatie binnen een website door middel van een menustructuur is grotendeels vervangen: er wordt gebruik gemaakt van de mogelijkheid om content te verfijnen op basis van tags. Om dit te realiseren wordt er gebruik gemaakt van het standaard RefinementPanel met een aangepaste filterdefinitie (inclusief bijbehorende managed/crawled properties) en xslt. Buiten het standaard RefinementPanel is er een custom refiner ontwikkeld welke content binnen een bepaalde tijdsperiode filtert.
Om de content te tonen is het Core Results webpart diverse keren geimplementeerd in een zeer aangepaste vorm. Content wordt dynamisch toegevoegd aan de zoekresultaten op de verschillende pagina’s middels intensief gebruik van http handlers, jQuery en JSON. Vanuit de zoekresultaten kan er genavigeerd worden naar het weergegeven type content. Foto’s en video’s worden getoond in een lightbox met extra informatie over het getoonde item.
Op de website wordt intensief gebruik gemaakt van het Content Query webpart. De nieuwe ‘slots’ functionaliteit wordt toegepast en er zijn nieuwe xslt item styles ontwikkeld.
Uiteraard is er een masterpage ontwikkeld en diverse page layouts om de website structuur te geven en van een consistente look & feel te voorzien in de stijl welke bij Oasen past. Het design van de website is zeer vernieuwend en dynamisch en brengt de nodige uitdagingen met zich mee in combinatie met SharePoint. Er is geen onderdeel in de website wat overeenkomt met standaard SharePoint design.
Buiten nieuw ontwikkelde functionaliteit zijn er diverse bestaande modules gemigreerd naar de nieuwe site. Als klant van Oasen kan er gebruik worden gemaakt van modules als het doorgeven van meterstanden of een verhuizing, het rekeningnummer wijzigen en het voorschot aanpassen.
Verder worden er grafieken over het waterverbruik getoond. Hier kan bijvoorbeeld mee worden bepaald wanneer de rust in een belangrijke voetbalwedstrijd is.
Diverse watermeters worden getoond om de hoeveelheid water aan te geven welke Oasen levert in diverse regio’s. Deze meters worden grafisch weergegeven door middel van flash technologie. Diverse modules hebben een BizTalk koppeling met achterliggende systemen.
Naast de beschreven (basis) functionaliteit zijn er vele onderdelen ontwikkeld, welke binnenkort op de website van Oasen zullen worden gepubliceerd op http://www.oasen.nl
Diverse onderdelen van SharePoint zijn gebruikt om de functionaliteit te kunnen realiseren, zoals sitecolumns, contenttypes, listinstances, jQuery, HTTP Handlers, application pages, css, xslt, page layouts, masterpage, custom actions, eventreceivers, workflows, user controls, webcontrols, webparts, delegates, timerjobs, Excel services.
De website van Oasen is een publieke website, waarbij performance en optimalisatie uitermate belangrijk zijn.
Voor de registratie van de te realiseren onderdelen is Team Foundation Server 2010 gebruikt. Anita is verantwoordelijk voor het bepalen van te realiseren onderdelen in elke sprint en het creeren van taken gerelateerd aan deze sprint backlog items. Daar Anita verantwoordelijk is voor de technische keuzes in het project is het van belang dat zij ook de inhoud van de sprints bepaalt, zodat er snel een basis voor de website staat. Mede omdat de doorlooptijd van het project maar 9 weken is. Voordat een sprint start wordt in een sessie met de engineers en designer de sprint backlog items verdeeld met in achtneming van de beschikbare uren van de projectleden en de te verdelen items. Tijdens het project is Anita verantwoordelijk voor de planning, voortgang en kwaliteit van het opgeleverde. Anita straalt rust uit over het team en staat ten alle tijde open voor vragen van elk lid van het projectteam.
SharePoint Server 2010, Visual Studio 2010, jQuery, JSON, xslt, Excel services, Team Foundation Server 2010, TFS Sidekicks, Imtech OCD, Scrum.
Search Refiners (part 4) – User selection based
In this series:
- Search Refiners part 1 – Expanding the OOTB search Refinement Panel
- Search Refiners part 2 – Use of CustomFilters
- Search Refiners part 3 – Chart based
- Search Refiners part 4 – User selection based (this post)
After building a chart based search refiner, now it’s time to get some interaction in the selection of search terms. In this post I will show you how to use jQuery in combination with the RefinementManager.
With interaction I mean the user can drag a search term to a place on the screen to refine the results. Unfortunately the OOTB Refinement Panel and the results webpart ‘talk’ to each other by the parameters in the url. Therefor a postback must occur to actually refine the results with the selected term. But a little animation just looks great.
For the drag and drop functionality I used the standard jQuery library and a custom jQuery UI selection. With this functionality in hand I created my own drag and drop implementation for this specific solution.
Script part
Because I already have a little experience with programming against the RefinementManager class in the chart based example I first focused on the drag drop functionality.
Two divs are placed on the screen:
1. to list all the terms the user can choose from to select
2. the already selected terms by the user
The items in both divs has to have the ability to drag items from and to drop items to. The user has to have the possibility to drag items from the ‘terms to select’ part to the ’selected terms’ part and vice versa.
Both the divs contain an unordered list with list items.
So a single div with items in it looks in plain HTML like:
<div> <ul> <li>item01</li> <li>item02</li> </ul> </div>
A single item has to be draggable to move it from the ‘terms to select’ to the ’selected terms’ part(and vice versa). So the li element has to be draggable.
On the other hand when a li element a dragged, the list to which the single item has to be added has to be droppable, the ul element.
To accomplish this just a few lines of jQuery are neccesary, the rest is alredy build in the jQuery libraries.
var $currentSelectedItems = $("#selectedTerms"),
$baseItemList = $("#termsToSelect");</pre>
//make the li's in the selectedTerms div draggable
$("li", $currentSelectedItems).draggable({
appendTo: $baseItemList,
helper: "clone"
});
//make the ul in the selectedTerms div droppable
$("ul", $currentSelectedItems).droppable({
accept: "#termsToSelect li",
hoverClass: "ui-state-hover",
drop: function (event, ui) {
moveTerm(ui.draggable, $currentSelectedItems);
}
});
The draggable functionality is nothing special. The element passed to appendTo is the container during dragging. Second the clone helper is used here, which means a clone of the actual item is dragged around. Another option here is original, which drags the original item around.
The droppable functionality uses different options. First I’m telling the element what items to accept: an li element within ‘termsToSelect’. Second a nice hover class and finally a function is specified what to do when the actual drop occurs: move the term to from ‘terms to select’ to ’selected terms’ and navigate to the url which the item received from the RefinementPanel (getting there soon).
//move term
function moveTerm($item, $listToAdjust) {
$item.fadeOut(function () {
var $list = $("ul", $listToAdjust);
$item.appendTo($list).fadeIn();
window.location.href = $item.find('a').attr("href");
});
}
The script above is the script which act on the ’selected terms’ part ($currentSelectedItems or $(“#selectedTerms”)). The same functionality have to be added to the ‘terms to select’ part. Because it’s almost the same this code it’s left out here for readability.
That’s is with all the script, let’s move the code behind all this.
The webpart
The code behind this (just a regular webpart) works with the RefinmentManager class of the page as in the chart based example, the previous post in this series. The extra functionality here is that the selected term is needed from the RefinmentManager’s filter. If a term is selected or not is just another node in the refinement xml, just as Value and Url as shown in the following code listing:
string filterValue = filter.SelectSingleNode("Value").InnerText;
string filterUrl = filter.SelectSingleNode("Url").InnerText;
if (filter.SelectSingleNode("Selection").InnerText.Equals("Selected"))
{
dateSelectedList.Add(new ListItem(filterValue, filterUrl));
}
else
{
dateToSelectList.Add(new ListItem(filterValue, filterUrl));
}
dateSelectedList and dateToSelectList are both generic lists of ListItems and in the RenderContents method the items in the lists are added to the appropriate containers.
After putting this all together it looks like the folowing image when no selection are made by the user:

When dragging starts from ‘terms to select’ the location where to drag to is highlighted:
Because ‘helper’ was set to ‘clone’ earlier the item that’s dragged, ‘Past Week’, is still in the ‘terms to select’ container and also moving around the screen.
When dropping the item for a moment the screen looks like (because of the ‘appendto’ option):
And then a postback occurs and it looks like:
And the terms displayed behave just like the OOTB refiners.
Summary
The OOTB refinement functionality is great, but it can be made much more attractive with just a little script as shown in this post. What I’ve shown you here is just a little example with one of the possibilities to make it more attractive. There are a lot of jQuery libraries with excellent functionality which you can use to do all kinds of stuff and don’t forget the design. This example looks nothing like a nice production ready refiner, but go wild and make it look awesome.
DIWUG SharePoint eMagazine 4
A couple of months ago Marianne van Wanrooij and I had a chat at one of the SharePoint conferences in The Netherlands. Before I realised I promised her to write an article for the awesome DIWUG SharePoint eMagazine.
Just kidding, I am pleased I could write an article!
Since I like the jQuery library for SharePoint WebServices called SPServices of Marc Anderson, the choice of a subject for the article wasn’t that hard.
Please download the magazine here and enjoy!
http://www.diwug.nl/Pages/downloads.aspx
Thanks to Marianne and Mirjam for publishing and thanks to Marc D Anderson for reviewing my article!
SDN Magazine
Recently I got the opportunity to write an article for the SDN magazine. SDN is an abbreveation of Software Developement Network and is a Dutch network. Alexander Meijers asked me if I had time and pleasure of writing an article for the SDN magazine, so I did. Here is a link to the contents of the magazine:
http://www.sdn.nl/SDN/Magazine/tabid/66/articleType/ArticleView/articleId/3003/SDN-Magazine-108.aspx
The articles will be soon available at the SDN site: http://www.sdn.nl.
Alexander, do you know when the articles will be available?
Search Refiners (part 3) – Chart based
In this series:
- Search Refiners part 1 – Expanding the OOTB search Refinement Panel
- Search Refiners part 2 – Use of CustomFilters
- Search Refiners part 3 – Chart based (this post)
- Search Refiners part 4 – User selection based
In the previous two posts about search refiners no code was written to adjust the OOTB Search Refinement Panel, just some XML modifications.
In this post a chart based search refiner will be built and some code is needed to accomplish this. The refinement will be built on the Modified Date.
Create the refiner
To get the refinement categories and their values, the RefinementManager class will be used.
The RefinementManager will get an instance of the refinement manager on the current page. This means the OOTB Search Refinement Panel has to be present on the current page. Not only it has to be present, it also has to have the filtercategory on which the refinement is going to perform on, in this case the Modified Date.
Get the instance of the refinement manager:
RefinementManager refinementManager = RefinementManager.GetInstance(this.Page);
To get the refinement values:
XmlDocument refinementXmlDoc = refinementManager.GetRefinementXml();
The GetRefinementXML method gets the filtered xml document of the refinement manager.
For the example is this post only the Modified Date is of interest, so an XPath expression is used to get to the right filter category and values:
XmlNodeList filters = refXmlDocument.DocumentElement.SelectNodes("/FilterPanel/FilterCategory[@ManagedProperty='" + refiner + "']/Filters/Filter[Count>0]");
The refiner variable is declared as:
private const string refiner = "Write";
By looping through the XMLNodes in the XMLNodeList the neccesary values are available, just as in the XML which is rendered by the OOTB Search Refinement Panel. The elements of the childnodes (filter categories) are shown:
Actually, this was the most interesting part. What’s left is displaying the values to the user, in this case: putting it in a chart; and binding it all together.
Putting it all together
In CreateChildControls the chart is setup:
private Microsoft.Office.Server.WebControls.Chart chart;
protected override void CreateChildControls()
{
ChartArea area = new ChartArea("Pie Chart");
chart = new Microsoft.Office.Server.WebControls.Chart();
chart.Width = 160;
chart.Height = 160;
chart.ChartAreas.Add(area);
Controls.Add(chart);
}
And in the OnPreRender the refiment manager, the values of the filter category Modified Date and the chart are put together.
protected override void OnPreRender(EventArgs e)
{
RefinementManager refManager = RefinementManager.GetInstance(this.Page);
XmlDocument refXmlDocument = refManager.GetRefinementXml();
if (refXmlDocument != null)
{
Series chartSeries = new Series();
chartSeries.ChartType = SeriesChartType.Pie;
XmlNodeList filters = refXmlDocument.DocumentElement.SelectNodes("/FilterPanel/FilterCategory[@ManagedProperty='" + refiner + "']/Filters/Filter[Count>0]");
if (filters.Count != 0)
{
foreach (XmlNode filter in filters)
{
string xValue = filter.SelectSingleNode("Value").InnerText;
string yValue = filter.SelectSingleNode("Count").InnerText;
int i = chartSeries.Points.AddXY(xValue, yValue);
// display text in chart
chartSeries.Points[i].Label = xValue;
//use the url to make the pie parts clickable
chartSeries.Points[i].Url = filter.SelectSingleNode("Url").InnerText;
}
//add 'Any Modified Date' option
XmlNodeList xmlFilterNodesAllItems = refXmlDocument.DocumentElement.SelectNodes("/FilterPanel/FilterCategory[@ManagedProperty='" + refiner + "']/Filters/Filter[Count='']");
chart.Titles.Clear();
System.Web.UI.DataVisualization.Charting.Title allItemsTitle = new System.Web.UI.DataVisualization.Charting.Title();
allItemsTitle.Text = xmlFilterNodesAllItems[0].SelectSingleNode("Value").InnerText;
allItemsTitle.Url = xmlFilterNodesAllItems[0].SelectSingleNode("Url").InnerText;
allItemsTitle.ToolTip = "Refine by: " + allItemsTitle.Text;
allItemsTitle.ForeColor = Color.FromArgb(0, 114, 188);
chart.Titles.Add(allItemsTitle);
}
if (chartSeries.Points.Count > 0)
chart.Series.Add(chartSeries);
}
}
In the XPath expressions used to get the filter values for Modified Date and ‘Any Modified Date’ are slightly different. Look at the Count differences.
By removing the Count in the first XPath expression the chart will display ‘Any Modified Date’ and the chart kind of gets messed up:

and ‘Any Modified Date’ is not clickable, because it get’s no colored part in the pie chart. The reason for this is that the Count value for Any Modified Date is empty.
This is the reason to use Count>0 for the values displayed in the pie chart and Count=” to get Any Modified Date.
The pie chart now looks like this:
And after selecting ‘Past Month’:
Summary
To transform a textual search refiner to a chart based search refiner is shown in this post.
As long as the OOTB Search Refinement Panel is present on the page and the filter category used by the code is present in the Filter Category Definition (property of Search Refinement Panel web part), the code in this post can be used to visualize a search refiner.
If it’s not present, you can extend the Refinement Panel webpart. This is not covered in this post, but maybe I’ll show you this in a future post.
Portal for Business
Branche: Informatie technologie
Januari 2011
SharePoint consultant/developer
Voor diverse klanten van Portal for Business heeft Anita de huisstijl toegepast op intranet sites door middel van het ontwikkelen van custom masterpages en style sheets.
Een intranet bestaat bij de klanten uit meerdere web applicaties. Om globale navigatie consistent te houden op de diverse web applicaties is er een custom site map provider ontwikkeld om dit te realiseren.
Hiernaast zijn er custom ribbon buttons ontwikkeld en een news aggregator webpart. Dit webpart verzamelt nieuws items van een bepaald niveau binnen een web applicatie tot alle onderliggende subsites en toont deze items.
De genoemde functionaliteiten zijn zowel voor SharePoint Server 2010 als voor SharePoint Foundation 2010 ontwikkeld. De solutions zijn zoveel mogelijk sandboxed solutions, tenzij de gewenste functionaliteit en daarbij behorende oplossing dit niet toelaat, zoals de custom site map provider.
SharePoint Server 2010, SharePoint Foundation 2010, Visual Studio 2010, jQuery
Search Refiners (part 2) – Use of CustomFilters
In this series:
- Search Refiners part 1 – Expanding the OOTB search Refinement Panel
- Search Refiners part 2 – Use of CustomFilters (this post)
- Search Refiners part 3 - Chart based
- Search Refiners part 4 – User selection based
The OOTB Search Refinement Panel can be expanded with CustomFilters. An example of the use of a default custom filter used in the OOTB Filter Definition is the Modified Date refiner.
This custom filter is of type RangeMapping. This means a range of values are mapped to a custom value.
The XML below shows the standard custom filters section of the Modified Date refiner.
<CustomFilters MappingType="RangeMapping" DataType="Date" ValueReference="Relative" ShowAllInMore="False"> <CustomFilter CustomValue="Past 24 Hours"> <OriginalValue>-1..</OriginalValue> </CustomFilter> <CustomFilter CustomValue="Past Week"> <OriginalValue>-7..</OriginalValue> </CustomFilter> <CustomFilter CustomValue="Past Month"> <OriginalValue>-30..</OriginalValue> </CustomFilter> <CustomFilter CustomValue="Past Six Months"> <OriginalValue>-183..</OriginalValue> </CustomFilter> <CustomFilter CustomValue="Past Year"> <OriginalValue>-365..</OriginalValue> </CustomFilter> <CustomFilter CustomValue="Earlier"> <OriginalValue>..-365</OriginalValue> </CustomFilter> </CustomFilters>
In this case the DataType is set to Date and the ValueReference to Relative. The DataType represents the type returning from the managed property and the ValueReference compares the data on a relative basis.
Besides the RangeMapping the mapping type ValueMapping can be used. This means a value can be used to map to a customvalue.
This type will be used in the following example.
Intro
To simply add a new custom filter let’s proceed with the example in the first post of this series.
In this example a number of documents were uploaded to the document library. In this library CarLease documents, Employee contracts and other types are stored. The documents are not ´typed´. It´s just the name of the document which suggests a type. Suppose the Employee contracts are the base contracts and other contracts are supplementary.
This distinction is what the search refiner has to show:
- Employee Contract
- Additional Contract
and not all the possible types of documents.
Create the refiner
To set the type of a document add a column named Document Type with some document type options like `Car Lease`, ´Health Care´ and ´Employee Contract´. Set the type of each document.

This is a simple way to ´type´ a document. A better real life approach is to create different content types and use these as the base of the documents to distinguish them. Just for now the column with the types is used.
This ´type´ is going to be used in the search refinement panel. Before it can be used a managed property has to be created and a full crawl of the content has to be performed. If you don´t recall how to do this, please check the first post in this serie.
The next step is to add a new refinement category in the refinement panel with the custom filter. The easiest way to define the XML is to use Visual Studio to get some indentation and coloring which will help you format the XML properly.
Copy the existing XML from the Filter Definition in the refinement panel and copy it in Visual Studio. In the first post of this serie a new category has been added, so now the focus is on the custom filter.
The parent element of a single custom filter the the CustomFilters element.
<CustomFilters MappingType="ValueMapping" DataType="String" ValueReference="Absolute" ShowAllInMore="False"> ... </CustomFilters>
Since the Document Type is just a piece of text the DataType is set to String. In the Modified Date example the Date type is used. Besides these two types the type Numeric can be used when appropriate.
The ValueReference is set to Absolute for comparison on an absolute basis. Other option is ShowAllInMore. When a user selects the ’show more’ option in the refiner more options for the refiner will be shown. In the Category definition an attribute NumberOfFiltersToDisplay is used which represents the number of filters to show at first glance. When more filters are present the ’show more’ link is displayed. Once selected the other filters are shown. With the ShowAllInMore option set to true all these filters are shown when selecting ’show more’, even if there are no results with this filter.
Now a custom filter can be defined:
<CustomFilter CustomValue="Employee Contract"> <OriginalValue>Employee Contract</OriginalValue> </CustomFilter>
The original value is the value of the property returned by the search, the custom value is a value you can choose youself to display in the search refinement panel.
The OriginalValue element is not limited to one. You can define multiple element to map to one custom value:
<CustomFilter CustomValue="Additional Contract"> <OriginalValue>Health Care</OriginalValue> <OriginalValue>Care Lease</OriginalValue> </CustomFilter>
Edit the search refinement panel and select the Filter Categoy Defintion.
After crawling and preparing the XML for the search refinment panel the property can be used in the search.
The full XML for the new Category with custom filters looks like this:
<Category Title="Document Type" Description="Type of document" Type="Microsoft.Office.Server.Search.WebControls.ManagedPropertyFilterGenerator" MetadataThreshold="3" NumberOfFiltersToDisplay="3" MaxNumberOfFilters="20" ShowMoreLink="True" MappedProperty="DocumentType" MoreLinkText="show more" LessLinkText="show fewer"> <CustomFilters MappingType="ValueMapping" DataType="String" ValueReference="Absolute" ShowAllInMore="False"> <CustomFilter CustomValue="Additional Contract"> <OriginalValue>Health Care</OriginalValue> <OriginalValue>Care Lease</OriginalValue> </CustomFilter> <CustomFilter CustomValue="Employee Contract"> <OriginalValue>Employee Contract</OriginalValue> </CustomFilter> </CustomFilters> </Category>
Test the refiner
Perform a search on one of the words in the title of one of the documents in the Document Library. Notice the Document Type refiner.

Notice the refiner displays only two filters, ‘Employee Contract’ and ‘Additional Contract’. Just as defined in the custom filters part of the XML.
Summary
Custom filters can be very useful to guide users in performing a search and refine the results. The example used here is just for demonstration purposes, but I guess you can think of something useful in your organisation. Maybe refiners on file size or different content types.
Search Refiners (part 1) – Expanding the OOTB search Refinement Panel
In this series:
- Search Refiners part 1 – Expanding the OOTB search Refinement Panel (this post)
- Search Refiners part 2 – Use of CustomFilters
- Search Refiners part 3 – Chart based
- Search Refiners part 4 – User selection based
Intro
A large multinational company has several contracts. These contract are stored in SharePoint. Based on the
multinational character of the company the contracts are stored in different languages.
Titles of the documents are all in English, so there is no way to determine from the title in what language the
document is written. Therefor a new column is introduced where the language can be stored.
This column in a lookup column to another list where all the languages are defined.
When people are searching for contracts there is no quick way to see in what language the document is written. To
prevent users to open multiple documents to see the language of the content a search refiner will help them out.
The existing OOTB refinement panel can be expanded just with XML.
Before doing so some preparations has to be done.
Create lists
First a custom list has to be created which will store the possible language values.
A document library has to be added to a site which will contain the documents for the contracts. An additional column
has to be added to let the user choose the language in which the document is written. This will be a lookup column to
the previous created list of languages.
A set of documents are uploaded with their languages set.

Crawl content
Start Central Administration, select Application Management and Manage Service Applications. Select Search Service
Application to display the Search Administration page.
Select Content Sources and start an incremental crawl.
Create managed property
When this is finished create a Managed Property called Language and add a mapping to the crawled property ows_Language.

Start a Full Crawl.
Check if any results are present in the crawled property.
Modify Filter Category Definition
Create an Enterprise Search Center and edit the Refinement Panel. In the webpart properties in the section Refinement
select the button next to the Filter Category Definition textbox to show all the text in it.
The XML is not difficult to read and understand when copying and pasting the XML into an XML file in Visual Studio..
Even without checking on the full Refinement Panel XML schema it’s pretty clear what to do by copying an existing
Category element and make some changes.
Full explanation of this schema can be found on MSDN here http://msdn.microsoft.com/en-us/library/ee819920.aspx �
Add to the filter category definition in the webpart properties:
<Category Title="Language" Description="Language of document" Type="Microsoft.Office.Server.Search.WebControls.ManagedPropertyFilterGenerator" MetadataThreshold="3" NumberOfFiltersToDisplay="3" MaxNumberOfFilters="20" ShowMoreLink="True" MappedProperty="Language" MoreLinkText="show more" LessLinkText="show fewer" />
Don’t forget to uncheck ‘Use default configuration’.
Unchecking this option is quite important. When this checkbox is selected any changes to the filter category definition
configuration are not persistent. A better experience would be disabling the Filter Category Definition when this
checkbox is selected…
Apply and save the changes.
Test the refiner
Start a search on one of the words in the title of one of the documents uploaded in the created Document Library.
Notice the Language refiner on the left.
The values displayed of the Language refiner is default sorted by count. This means the value which is used most
appears on top.
Refiner is not showing
When the refiner is not showing in the Search Center there are a few things to check.
- Make sure to fully crawl the content after creating the managed property and confirm the crawled property contains
values. - Make sure there is enough data which uses in this case the language. In the above XML the value of the
MetadataThreshold attribute is set to 3. This means the number of results that must contain a value to display the
filter generator under the filter category is set to 3. - Uncheck Use Default Configuration in the webpart properties of the Refinement Panel, section Refinement.
- In the webpart properties of the Refinement Panel in the secion Refinement a value is displayed for Number of
Categories to Display. If the number of categories exceeds this number and the new category is defined last in the XML,
it won’t show up.
Summary
SharePoint provides OOTB an easy way to create your own search refiners.
A crawled property, content and some XML to define the filter category are sufficient.
Access denied when activating a feature
This is the title of a question posted at SharePoint Overflow and got my attention.
I checked out the issue and I had a suspicion it had to do with the user not being a farm administrator. But before answering the post I had to make sure and tested it on my dev machine.
I fired up Visual Studio, create a feature with a feature receiver and wrote some code in the FeatureActivated method to update the web.config file en deployed it from Visual Studio to the SharePoint environment. All went well and the web.config received the modification.
To really make sure I tested this with another user (no farm administrator) by activating the feature from the browser. I received the error described in the post at SharePoint overflow:
<System>
<Provider Name="Microsoft-SharePoint Products-SharePoint Foundation" Guid="{6FB7E0CD-52E7-47DD-997A-241563931FC2}" />
<EventID>6615</EventID>
<Version>14</Version>
<Level>2</Level>
<Task>10</Task>
<Opcode>0</Opcode>
<Keywords>0x4000000000000000</Keywords>
<TimeCreated SystemTime="2011-02-02T12:43:36.717773400Z" />
<EventRecordID>12679</EventRecordID>
<Correlation ActivityID="{E64F5E21-D27E-46B5-99A6-1366EBD456F5}" />
<Execution ProcessID="1768" ThreadID="7100" />
<Channel>Application</Channel>
<Computer>SP2010</Computer>
<Security UserID="S-1-5-21-3420107791-3555115667-1280696338-1015" />
</System>
<EventData>
<Data Name="string0">Access denied.</Data>
</EventData>
and the ULS log mentioned:
The SPPersistedObject, SPWebService, could not be updated because the current user is not a Farm Administrator.
To really really be sure I made the user a farm administrator and tried to activate the feature from the browser: Access denied.
Well, this user is a Farm Administrator now, so why the error?
I removed the user from the Farm Administrators group because I though I did something wrong and tested the activation of the feature in the browser with the farm administrator account: Access denied.
Oww, what’s this?
Suddenly it seemed broken, probably it was broken all the time, because I deployed it from Visual Studio directly and never tested it by activating the feature from the browser with this account.
Deploying and activating the feature from Visual Studio went well and the web.config modification was there, but as soon I activated the feature from the browser I received an Access denied message.
Maybe a timerjob had to run or something, so I checked and waited for a while. Nothing changed.
IISReset, application pool recycle. Nothing changed.
Restarting the server. Nothing changed.
When Googling on the ULS log message this post came up:
http://unclepaul84.blogspot.com/2010/06/sppersistedobject-xxxxxxxxxxx-could-not.html
It was a different matter, but the behaviour seemed to be the same.
A summary of that post:
“Upon detailed investigation of Microsoft.SharePoint.dll I discovered that SharePoint guys added a new security feature to all objects inheriting from SPPersistedObject in the Microsoft.SharePoint.Administration namespace. This feature explicitly disallows modification of the above stated objects from content web applications, which is where our web part is running. The error message thrown is therefore very misleading. After some more tracing through the code I found a property in SharePoint API which controls this behavior:
Microsoft.SharePoint.Administration.SPWebService.ContentService.RemoteAdministratorAccessDenied”
A PowerShell script is added to that post which turns off the remote administration security.
That did the trick!
The feature which modified the web.config could be activated from the browser again and the Access denied messages were not occurring anymore.
The ultimate test: a regular user was turned into a farm administrator and a site collection owner. This user is now also able to activate the feature from the browser to make a web.config modification.
Serious considerations
There are some serious considerations on this:
The Feature created was a Web scoped feature. When turning off the remote administration security this feature can be activated from any site. But when modifying web.config keys it’s the question if you want to be able to do this from any site.
I think Central Administration is the place to keep features like this. When deploying a feature which modifies web.config keys it’s an administration thing and not a users thing. By the way: if you’re not a farm administrator you get an Access denied message anyway when trying to activate such features if remote administration security is turned on.
So I really doubt it if you have to turn off remote administration security in this example. Rather deploy the feature to the Central Administration.



