MOSS People Search Provider For IE8
In this post, and the one following it I will present two new search providers for MOSS 2007.
Search provider is an old feature of common browsers, IE8 brings it into a new level with the extended visibility it provides for search results.
You can read more about IE8 search providers IE8 search provider.
The two search providers I will present will be:
1. People search provider for searching people in the portal.
2. Documents search provider for searching documents in the portal.
As we all know MOSS comes with a build-in search capabilities which includes a search engine and a very nice UI for search queries and search results. These two new providers are intended to extend these capabilities so users can search the portal before they actually access it.
My example is depending on Guy Burstein twitter search provider and I thank him for his direction in writing this post.
The example was developed as a regular service which has to be installed on the same machine where the portal is. It can be also deployed as a windows service exposing the service as WCF or as feature installed inside MOSS. In order to keep it simple I will only present the initial version.
Search providers are combined of 3 main parts:
1. The service
2. The XML defining the service
3. Client side script for installing the provider
The service
In order to search people inside the portal we must have a portal with indexed defined profiles. I won’t demonstrate how this is accomplished because it’s out of this post’s scope. In my example I simply imported the profiles from our Active Directory.
The service itself contains 2 parts:
1. Interface
2. Implementation of that interface as a service
The interface looks like this:
[ServiceContract]
public interface IPeopleSearchService
{
[OperationContract]
[WebGet(UriTemplate = "/Search?q={friend}",
BodyStyle = WebMessageBodyStyle.Bare)]
[XmlSerializerFormat]
SearchSuggestion Search(string friend);
}
As you can see, a very simple interface with a single method the receives a single variable which is the phrase we will be searching.
The Implementations:
public class PeopleSearchService : IPeopleSearchService
{
#region IPeopleSearchService Members
public SearchSuggestion Search(string friend)
{
var oFrt = new FullTextSqlQuery(new SPSite(ConfigurationManager.AppSettings["server"]));
oFrt.QueryText = string.Format(ConfigurationManager.AppSettings["query"].Replace('@', '"'), friend);
oFrt.ResultTypes = ResultType.RelevantResults | ResultType.SpecialTermResults;
oFrt.StartRow = 0;
oFrt.RowLimit = 10;
oFrt.TrimDuplicates = true;
ResultTableCollection lstResults = null;
lstResults = oFrt.Execute();
var ds = new DataSet();
ds.Tables.Add("results");
ds.Tables["results"].Load(lstResults[ResultType.RelevantResults]);
var results = new SearchSuggestion();
results.Query = friend;
foreach (DataRow row in ds.Tables["results"].Rows)
{
try
{
if (row["pictureurl"] != null && row["pictureurl"].ToString() != string.Empty)
{
results.Section.Add(new Item
{
Text = row["title"] + " , " + row["department"],
Description = row["workphone"] + " , " + row["workemail"],
Url = row["path"] + Environment.NewLine + Environment.NewLine,
Image =
new Image
{Height = 48,
Width = 48,
Source = row["pictureurl"].ToString()
}
});
}
else
{
results.Section.Add(new Item
{
Text = row["title"] + " , " + row["department"],
Description = row["workphone"] + " , " + row["workemail"],
Url = row["path"].ToString(),
Image =
new Image { Height = 48,
Width = 48,
Source = ConfigurationManager.AppSettings["server"]+"/_layouts/images/no_pic.gif"
}
});
}
}
catch (Exception ex)
{
results.Section.Add(new Item {Text = ex.Message, Description = ex.StackTrace, Url = ""});
}
}
return results;
}
#endregion
}
As you can see I was using Guy’s search suggestions class to generate the response using search results coming from the query search results. (The query is defined in the web.config so it can be easily altered during development) You can change the fields you ask for in the query so you can present different content in the search results.
I used title and department for the Text field and workphone + workemail for the Description field and the path as Url so clicking a search result will navigate to the personal page of the person.
Image is set by the pictureurl in case the search result contains a pictureurl, otherwise the default image is presented.
(Catch(Exception ex) returns the exception for debugging but it should be removed)
The XML defining the service
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>People Search</ShortName>
<Url
type="text/html"
template="http://doron-g/SearchCenter/Pages/peopleresults.aspx?k={searchTerms}"
/>
<Url
type="application/x-suggestions+xml"
template="http://localhost:52985/SearchProviders/PeopleSearchService.svc/Search?q={searchTerms}"
/>
<Image
height="16"
width="16"
type="image/icon">http://www.netwise.co.il/Images/favicon.ico
</Image>
</OpenSearchDescription>
The XML is the standard XML for search providers, which contains two URL’s – one for navigation in case the user hits Enter in the search box which navigates him to my portal’s default people’s search results page and one for the service which will be addressed while the user is typing inside the search box. (The service we created earlier)
Client side script
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function Register()
{window.external.AddSearchProvider('PeopleSuggestion.xml');}
function RegisterDocumentSearch()
{window.external.AddSearchProvider('DocumentSuggestion.xml');}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<button onclick='Register();'>People Search</button>
<br />
<button onclick='RegisterDocumentSearch();'>Document Search</button>
</div>
</form>
</body>
</html>
The script is the standard script for adding search providers - window.external.AddSearchProvider with the XML location as a parameter.
(This file contains both providers, the documents search provider will be presented in the next post)
The entire solution looks like this: (For both services)
When browsing to Default.aspx we have two buttons, one for each search provider:
Clicking the first button opens the add search providers dialog:
(Notice the Use search suggestions from this provider check box – unique for IE8)
After adding the provider it is now available for me on the search providers box:
Selecting it and typing my name results like this:
Searching other people, some with image and some without:
Clicking a search result leads me directly to the person’s page:
Hitting enter in the search box leads me to my portal’s people search results page:

I would like to thank Yuval Korin for his help in creating this example.