in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Tobias Zimmergren's thoughts on development - MOVED!

THIS BLOG HAS MOVED!!!
NEW URL: www.zimmergren.net
Please update your RSS and bookmarks!

Any comments here will not be answered, please comment on http://www.zimmergren.net instead!
All the same posts are there

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.sharepointblogs.com/zimmer

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:

  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:
  6. <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:

  7. 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>";
  8.         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.

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.

Download the UserControl here

Comments

 

SharePoint link love: 1-13-2008 at Virtual Generations said:

Pingback from  SharePoint link love: 1-13-2008 at  Virtual Generations

January 13, 2008 10:40 AM
 

Links (1/13/2008) « Steve Pietrek’s SharePoint Stuff said:

Pingback from  Links (1/13/2008) &laquo; Steve Pietrek&#8217;s SharePoint Stuff

January 13, 2008 6:46 PM
 

Adam Casey said:

Could someone test my usercontrol for me, it doesnt seem to work probly

<%@ Control Language="C#" AutoEventWireup="true" %>

<%@ Register Assembly="AjaxControlToolkit"

            Namespace="AjaxControlToolkit"

            TagPrefix="cc1" %>

<script runat="server">

   // If there were any server side code, it would go here since I don't use a code behind or pre-compiled assembly to host the code

</script>

<link href="StyleSheet.css" rel="stylesheet" type="text/css" />

           <cc1:CollapsiblePanelExtender ID="CollapsiblePanelExtender1" runat="server"

               TargetControlID="PnlContent" ExpandControlID="PnlTitle" CollapseControlID="PnlTitle"

               TextLabelID="Label1" CollapsedText="Show Details (...)" ExpandedText="Hide Details (...)"

               ImageControlID="Image1" ExpandedImage="images/collapse_blue.jpg" CollapsedImage="images/expand_blue.jpg"

               Collapsed="True" SuppressPostBack="true" >

           </cc1:CollapsiblePanelExtender>

       <asp:Panel ID="PnlTitle" runat="server" CssClass="collapsePanelHeader">

           <asp:Image ID="Image1" runat="server" ImageUrl="images/expand_blue.jpg" ></asp:image>

           <asp:Label ID="Label1" runat="server" Text="Show Details(...)" ></asp:Label>

       </asp:Panel>

       <asp:Panel ID="PnlContent" runat="server" CssClass="collapsePanel">

       Hello

       </asp:Panel>

it uses collapsible panel to hide/show text

thank you, i will check back here

January 15, 2008 3:18 AM
 

SharePoint, SharePoint and stuff said:

HowTos Adding Code-Behind Files to Master Pages and Page Layouts in SharePoint Server 2007 Adding Custom

January 16, 2008 3:03 AM
 

Mirrored Blogs said:

HowTos Adding Code-Behind Files to Master Pages and Page Layouts in SharePoint Server 2007 Adding Custom

January 16, 2008 3:27 AM
 

WorldsGreatestSharePointBlog said:

You really do have the greatest blog as you keep saying on your tutoring haha ;). Very good pointers and sample really. keep the work up man! See you

January 17, 2008 11:37 AM
 

Tobias Zimmergren said:

Adam, please see the reply to your mail and notify me if you've got further questions.

January 17, 2008 2:48 PM
 

patrick said:

Hi Tobias

great article!

For it works perfectly with one problem. The reload only works once. that means after the first "AJAX-Call" i get results. when i click a second time. nothing happens..

any ideas?

regards

patrick

January 31, 2008 10:52 AM
 

Nihal said:

hello zimmergren. i follow your blogposts about the ajax and stuff and it all works good. thanks for the help.

do you have any advanced webparts or usercontrols you have done to share? thanks again for good blogg

February 4, 2008 4:05 PM
 

Glenn said:

have some problems i have mailed to you hope you dont mind. its about the objectmodel with searching and not only ajax.

February 20, 2008 7:13 AM
 

Mike Fagan said:

Like Adam, I am also having issues with the collapsible panel.  It will not collapse completely and hide the lblBody Label.  Please advise.

<asp:Label ID="lblBriefBody" runat="server" Text="Label"></asp:Label>

       <asp:Panel runat="server" ID="PanelOOScopeHeader">

           <asp:Image ID="ImageOOScope" runat="server" AlternateText="Click me" ImageUrl="hdlmcdw1/.../collapse.jpg" />

           <asp:Label ID="Label3" runat="server" Text="Out of Scope Section" ></asp:Label>

       </asp:Panel>

       <br />

       <asp:Panel runat="server" ID="PanelOOScope">

       <asp:Label ID="lblBody" runat="server" Text="Label"></asp:Label>

       </asp:Panel>

       <cc1:CollapsiblePanelExtender ID="cpOOScope" runat="server"

           TargetControlID="PanelOOScope"

           CollapsedSize="0"

           ExpandedSize="300"

           ExpandControlID="PanelOOScopeHeader"

           CollapseControlID="PanelOOScopeHeader"

           Collapsed="true"

           AutoCollapse="False"

           AutoExpand="False"

           ExpandDirection="Vertical"

           ImageControlID="ImageOOScope"

           ExpandedImage="hdlmcdw1/.../collapse.jpg"

           ExpandedText="Collapse"

           CollapsedImage="hdlmcdw1/.../expand.jpg"

           CollapsedText="Expand"

           SuppressPostBack="true"

           />

March 25, 2008 1:23 PM

Leave a Comment

(required )  
(optional )
(required )  
Add

Need SharePoint Training? Attend a SharePoint Bootcamp!

Posts (c) their respective authors. Everything else (c) 2007 SharePoint Experts