search blog
most popular
MCP MCTS MCT MVP

MOSS 2007: Creating a custom AJAX UserControl that will query the SharePoint Search Query Object Model to perform searches

Author: Tobias Zimmergren
Url:
http://www.zimmergren.net

If you've read my last two blogposts you already know how to configure ASP.NET 2.0 AJAX for your SharePoint Server and how do deploy a UserControl that uses AJAX functionality on you SharePoint Server.

You can find my previous articles here:

This blogpost shows a simple implementation of a UserControl that uses the Object Model to query the search service using a keyword and then using an UpdatePanel in AJAX to present the result to the user without any page reloads.

Let's create an AJAX based UserControl which purpose will be to search using the Search Query Object Model

Copy the nessecary assemblies to your local bin folder (I'm deploying locally to the WebApplication on port 80)

To make this work (in this case, since I'm deploying to the UserControls folder with inline code, not calling any own assemblies) you need to copy the two .dll files to your /bin folder of the WebApplication where you want to deploy this UserControl.

  1. Copy C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI\Microsoft.Office.Server.dll
  2. Copy C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI\Microsoft.Office.Server.Search.dll
  3. Paste the two files to C:\Inetpub\wwwroot\wss\VirtualDirectories\80\bin\ (Note: It can be any other port other than 80 if you're deploying to another WebApplication)

The reason that we copy these files to our deployment target's /bin is simply that I'm deploying locally to that WebApplication and some of the namespaces and classes that we need to use in order to be able to query the Search Object Model are availible in those assemblies. There's better ways to accomplish this, but to keep it simple I'm going with this approach.

Create the custom AJAX UserControl that will query the SharePoint Search Query Object Model

For simplicity, I'll reference all the servercode inside the <script> block and not using a code-behind assembly.

  1. Launch Visual Studio 2005 (or whatever version you're running)
  2. Create a new file based on the "Web User Control" template, name it as you please
  3. Add the following tags just below the Control directive:

    <%@ Register Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TagPrefix="asp" %>
    <%@ Import Namespace="Microsoft.Office.Server" %>
    <%@ Import Namespace="Microsoft.Office.Server.Search.Query" %>
    <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>


    It could look something like this:
     searchajax1
  4. Just below all the references you just added, add the following code:

    <script runat="server">

    </script>


  5. Add the following code right below the references you just added. This code is simply to give us a simple user interface for the user to perform the search from:

    <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
        <ProgressTemplate>
            <img src="http://zimmergren/hostedImages/ajax-loader.gif" alt="Searching..." style="border: 0px none #fff;"/>
        </ProgressTemplate>
    </asp:UpdateProgress>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            Enter a keyword to search for<br />
            <asp:TextBox ID="tbSearchString" runat="server" Width="230px"/><br />
            <asp:Button ID="btnSearch" runat="server" Text="Search" OnClick="btnSearch_Click" />
            <asp:Literal ID="literalSearchResults" runat="server" />
        </ContentTemplate>
    </asp:UpdatePanel>


    It could look something like this:
     searchajax2

  6. Insert this code inside the <script>-tag you created earlier:

    protected void btnSearch_Click(object sender, EventArgs e)
    {
        // Job insurance, to pause and show that the UpdateProgress works
        System.Threading.Thread.Sleep(2000);
        try
        {
            string startTable = "<table style=\"width: 100%;\">";
            string endTable = "</table>";
            string searchResultItem =
            "<tr>" +
                "<td><a href=\"{0}\">{1}</a></td>" +
            "</tr>" +
            "<tr>" +
                "<td>" +
                    "<em>{2}</em>" +
                "</td>" +
            "</tr>" +
            "<tr>" +
                "<td>Site: {3}</td>" +
            "</tr>" +
            "<tr>" +
                "<td style=\"padding-bottom: 10px;\">Author: {4}, Item Size: {5}</td>" +
            "</tr>";

            string outputResults = startTable;

            ServerContext context = ServerContext.GetContext("SharedServices1");
            KeywordQuery keywordQuery = new KeywordQuery(context);

            keywordQuery.ResultTypes = ResultType.RelevantResults;
            keywordQuery.EnableStemming = true;
            keywordQuery.TrimDuplicates = true;
            keywordQuery.QueryText = tbSearchString.Text;

            ResultTableCollection results = keywordQuery.Execute();
            ResultTable resultTable = results[ResultType.RelevantResults];

            if (resultTable.RowCount == 0)
            {
                literalSearchResults.Text = "Sorry, your search didn't return any results";
            }
            else
            {
                while (resultTable.Read())
                {
                    outputResults += string.Format(searchResultItem,
                        resultTable.GetString(5),
                        resultTable.GetString(2),
                        resultTable.GetString(6),
                        resultTable.GetString(8),
                        resultTable.GetString(3),
                        resultTable.GetString(4));
                }
            }
            outputResults += endTable;
            literalSearchResults.Text = outputResults;
        }
        catch (Exception ex)
        {
            literalSearchResults.Text = ex.Message;
        }
    }

    Instead of going all crazy about how the code actually works with the Search Query Object Model, I'm just pasting the code here for you to try and will explain the Search Query Object Model in another article.

Deploy the UserControl
  • Copy or Save the UserControl to the following location: C:\Inetpub\wwwroot\wss\VirtualDirectories\80\UserControls\ and you're all set.

If you've configured AJAX and installed the SmartPart you should be all set and be able to use it. See this short post on using the SmartPart if you don't know already.

Final Result

This is what it looks like when you hit the button (the red image spins around for 2 seconds (see the code, Thread.Sleep(2000)) to show how it will look if it's a heavy query and needs some loading time.
 searchajax3

This is what the result will look like, note that everything is done within an UpdatePanel and we do not experience the page to reload, or any visual postbacks.
 searchajax4

Download the UserControl here


Published: Mar-13-08 | 6 Comments | 0 Links to this post

SharePoint Cross List Queries in a custom UserControl

Author: Tobias Zimmergren
Url:
http://www.zimmergren.net

I got the question last week weather it's possible to get items from all lists of <your chosen type here> gathered and displayed on one page.
This is - like most things - possible in SharePoint without any greater efforts. With something called Queries we can use the object model to query SharePoint and get a result quite painlessly.

To demonstrate a very simple example, I've created a very small usercontrol (for use with Jan Tielen's SmartPart) that looks like this:

 crossqueries1

This code will combine all the items in all of the TaskLists on the current SiteCollection and display them in a simple GridView as seen above in the screenshot.

Code for the Cross List Query UserControl

 crossqueries2

 crossqueries3

Simple enough, huh?
Of course you can create webparts, usercontrols, application pages, or any other type of application to interact with the object model in this way. I chose to do it using a UserControl for the ease of deployment, testing, development and demonstration.

For your conveniance I've uploaded the UserControl (.zip) here so you can download it.


Published: Mar-09-08 | 6 Comments | 0 Links to this post

MOSS 2007: Customizing the Search Results Page (XSLT) - Part 2 - Add highlighting

Author: Tobias Zimmergren
Url:
http://www.zimmergren.net

In one of my previous blogposts I wrote about how you easily could alter the XSLT of a the Search Core Results Web Part on your Search Results Page in order to achieve a customization to the presentation of the output.

In this article I will scratch on the surface of some more XSLT and show you how you can implement the HitHighligting Template in order to achieve colored/customized display of the search words you entered.

What is the HitHighligting Template?

Well, basically the HitHighligting template offers you the ability to highlight words that are used in your search. It offers you the possibility to highlight words in the following three result sections: Title, Url and Description (And that's basically all you need, mostly)

 searchresultstwo1

Study the following XSLT, as per MSDN:

<hithighlightedsummary>
  <c0>SharePoint</c0> <c1>namespace</c1> provides types and members that can be used for working with a <c0>SharePoint</c0> site  <ddd /> a top-level <c2>class</c2> that represents a <c0>SharePoint</c0> site and provides access to its collection of subsites <ddd /> <c0>SharePoint</c0> <c1>namespace</c1> and a brief description of each.
</hithighlightedsummary>
<hithighlightedproperties>
  <HHTitle>Microsoft.<c0>SharePoint</c0> <c1>Namespace</c1></HHTitle>
  <HHUrl>
http://msdn.microsoft.com/library/default.asp?url=/library/en-     us/spptsdk/html/tsnsMicrosoft<c0>SharePoint</c0>_SV01017995.asp</HHUrl>
</hithighlightedproperties>

You may notice that the sections hithighlightedsummary, HHtitle and HHUrl elements contain childs (<c0>,<c1> etc). This basically means that for each instance of the words entered in your search, you get a set of highlight-tags that encloses that word. This is the default behaviour of the SharePoint Search. First word gets <c0>, second word gets <c1> and so on...

How do I add the Highlighting functionality?

Note: If you do not know how to access the XSLT of the Search Core Results Web Part, view my previous post on the subject.

In order to customize the presentation of the search result and make your words highlighted, you basically only need to add some tags to the XSL-template for each search word you want to highlight as you can see in the screenshot below.

Now locate the following section in your Search Core Results Web Part (It already exist):

<xsl:template name="Hithightlighting">

And since this template exists from the beginning, all you really have to do is to customize the style attribute and add a color property of the <b> tag (I replaced it with a <strong> tag instead, for sake of standards)
Then you can simply specify the styles for each highlighted word as picted in the following screenshot:

 searchresultstwo2

It's simple as that. I hope this helped some of you to get started on some basic Search Core Results XSLT customizations.


Published: Sep-01-07 | 3 Comments | 0 Links to this post