November 23, 2007 12:11 AM

The Search Is On: Part II

Creating a Custom SharePoint Web Part
DevConnections
Rating: (0)

asp:Feature

LANGUAGES: C#

ASP.NET VERSIONS: 2.0

 

The Search Is On: Part II

Creating a Custom SharePoint Web Part

 

 

This two-part series guides you through the process ofcreating a SharePoint Web part. We began with the out-of-the-box configurationsrequired to ensure that search is successful inside your Microsoft OfficeSharePoint Server portals, and explored where the search result and click-throughdata is kept (see PartI). Now the challenge is to use this knowledge to build our own custom Webpart.

 

Building Your Query Report Control

With the system set up, you need end users to performsearches. As those searches are performed, you?ll need a customized way todisplay them sorted by popularity. Luckily, this information can be extractedand displayed on a Web page or in a Web part. Because the information is simplyin the database, there are a few options for accessing the data. You couldaccess the data by connecting directly to the database, you could write a Webservice, or you could even use the SharePoint classes to help build acomponent. It is important to keep in mind that these internal SharePointstored procedures could change with any hot fix or service pack, and are notdocumented as interfaces to the system. As we?ll briefly explore, each one ofthese options offers advantages and disadvantages.

 

If you connect to these stored procedures directly fromcode, you must write your own user and role security and database connectionmethods, provide the correct stored procedure, and provide the correctparameters. This can be a viable option, but you?ll need to provide your dataaccess code rights to the SharePoint database. If the SharePoint machine andthe Web server on which you are working are in the same environment, this canusually be worked out with administration settings.

 

The second option, using Web services, works best withapplications that need remote connections. For instance, you could display thisinformation to end users in a smart client (like Microsoft Word or your ownWindows Forms application). Although this helps distribute the data, the Webservice itself would still need to make a connection to the database (either withdirect access to SQL Server or through another method, such as using theSharePoint object model).

 

The third option, and the one we are going to take, is touse SharePoint?s own classes to pull information from the Search Query Results.This method includes the requirement of having SharePoint installed on one ofthe machines, but does not require you to write the database calls or thesecurity permission code.

 

To build this component, start by looking at the classhierarchy of Microsoft.SharePoint.Portal.Analytics.UI. Figure 1 shows how theclasses are inherited. These are the classes that power the usage reportsscreens and provide the fundamental classes that are used for the component.You?ll be creating a custom report control that would be at home on any of theusage report pages; however, this control is repurposing the data the reportwould use for display purposes. Having done this, you can take that data anduse it in any Web page using simple ASP.NET controls.

 

TopQueriesReportControl

 

QueryTopLargeListReportControl (abstract)

 

QueryTopReportControl (abstract)

 

QueryReportControl (abstract)

 

ReportControl (abstract)

Figure 1: Report controlhierarchy.

 

The component will derive fromQueryTopLargeListReportControl to get the functionality provided to all reportcontrols based on the search queries. When implementingQueryTopLargeListReportControl, you are required to implement certainproperties that each class must implement; these properties are shown in Figure2.

 

Property

Description

RdlFileName

When the report page is displayed this is the report definition file that will be used for formatting.

StoredProcedureName

The stored procedure that will be called to populate the data of the report.

Figure 2: Propertydefinitions for QueryTopLargeListReportControl.

 

From your previous research, you might recall that thestored procedure used for this control is proc_MSS_QLog_TopQueries. This samplecontrol has the string built in to the control, but you could easily make thisa property that can be modified through the user interface in order to create amore generic TopQueries control. The RdlFileName will be left blank because youwon?t actually be using the Report Control portion of this component. If youwant to use this control as a report control, or for testing purposes, simplyset the RdlFileName to the report you want to use. The RdlFileName could be oneof the existing Microsoft ones, or even a custom one you write. Once you?veimplemented the class, your code will start to look like that shown in Figure 3.

 

public class DevCowTopQueries: QueryTopLargeListReportControl

{

   protected overridestring StoredProcedureName

   {

       get

       {

           return"proc_MSS_QLog_TopQueries";

       }

   }

   protected overridestring RdlFileName

   {

       get { throw newException("The method or operation

             is notimplemented."); }

   }    }

Figure 3: New controlDevCowTopQueries.

 

Even though you are only required to implement twoproperties, the control also needs two other properties that are specific tothis control: TitleText and StoredProcedureParameters (see Figure 4). TheTitleText property is part of the reporting and control, and is only set forcases that the report control is used; the StoredProcedureParameters propertyis critical to the stored procedure you are using. From looking at the databasestored procedure, we can tell there are three parameters required ? one ofwhich controls the number of results returned. The values used are inheritedfrom the base classes, and only need to be implemented if you want to overridethem. For instance, the base value for TopResultCount is 10; if you want tohave this variable, or if you want to increase this number, you can overrideyour own property and set the value required.

 

protected override string TitleText

{

 get

 {

   return "DevCowQuery Control";

 }

}

 

protected override Collection<SqlParameter>StoredProcedureParameters

{

 get

 {

   Collection<SqlParameter>storedProcedureParameters = new Collection<SqlParameter>();

   Guid guid =SPControl.GetContextWeb(this.Context).Site.ID;

   storedProcedureParameters.Add(new SqlParameter("@siteGuid",guid));

   storedProcedureParameters.Add(new SqlParameter("@isSspLevel",this.IsSspLevel));

   storedProcedureParameters.Add(newSqlParameter("@topResultsCount", this.TopResultsCount));

   returnstoredProcedureParameters;

 }

}

Figure 4: DevCowTopQueriesproperties.

 

Here?s where your control begins to differ from thestandard Microsoft controls. The Microsoft controls keep the report datainternal to the control, but the entire idea of this control is to use thatdata on other Web pages. Luckily, one of the inherited method calls isLoadReportData, which doesn?t take any parameters and returns a System.Data.DataTable.To allow this data to be exposed to the end user, you must create a new method,GetData:

 

public DataTable GetData()

{

   returnthis.LoadReportData();

}

 

You can see that the method has the identical signature tothe LoadReportData method, and is, in fact, simply a wrapper method to allowother applications to access otherwise private data. Keep in mind that thisclass does not perform any security checks or audit logging on this method, butthese security checks or audits might be required, depending on theenvironment. Now that you are returning the data in a DataTable to other Webparts, Web pages, or controls, there?s no more mystery for the experienceddeveloper using the control to take advantage of Search Query data.

 

Display Top Search Terms

Now that the search data is being retrieved from theSharePoint analytics classes, you need a way to display this data on a Webpage. Because you are already using SharePoint to pull the data back, creatinga few Web parts to make it easy to display the results and create thefunctionality to use the results to perform your own search is the best option.To set the values of the dropdown list, you first must know the names of eachcolumn of the DataTable. You could look at the return types of the stored procedure,but in some cases it?s not obvious from the T-SQL. You could run the storedprocedure and see the values, or you could opt to create a GridView-based Webpart to dump the raw data to the screen. Here, a GridView Web part is avaluable exercise, perhaps to display the results for administrators, as illustratedin Figure 5. Administrators may want to see the entire view of the data thatwill be displayed to the end users in another format.

 


Figure 5: TopSearchTermsGrid Web part.

 

You can see that all the columns are information from thesearch pages discussed when you set up the page. These include the querystring, the search scope, and the results URL, to name a few. Additionally, youcan see information such as the number of times the query has been sought. Althoughthis is a simple Web part, it can be placed on any page to see the results and forwhat users are searching. Once you know what the users are looking for, you canadd best bets and improve the relevance of information that should show upbased on actual user search patterns.

 

With all this information, you can now build a Web partthat has a dropdown list of the top search queries run on the system. Remember,you are building components and Web parts to help the end users know the mostpopular search phrases on the site, and this is one way to help them expandtheir knowledge of the site without generating a lot of IT support calls. Thesalient field available for use is the queryString field, which is used forboth the displayed text and the value for searching. Figure 6 shows the call tothe control you just built to get the data, as well as using the data containedin the queryString column to populate the dropdown list values.

 

ddlTopChoicesClient = new DropDownList();

DevCowTopQueries tdd = new DevCowTopQueries();

 

ddlTopChoicesClient.DataSource = tdd.GetData();

ddlTopChoicesClient.DataTextField = "queryString";

ddlTopChoicesClient.DataBind();

this.Controls.Add(ddlTopChoicesClient);

Figure 6: Bindingto usage data.

 

The dropdown list allows the Web part to present the usera pre-defined list of query string selections and also prevents them frommodifying the list. This user experience lends itself to the collaborativenature of the Web part?s intention. If the user wants to search for informationnot directly related to the available search options, they?ll have to performthat search using the default search input control.

 

Build a GO Button

The GO button is the button that will perform the actualsearch action. There are many ways you can perform a search with SharePoint. Youcan type in the search URL with a query string, call the Web services API, usethe object model to perform the search, and use the built-in JavaScript. Forthe purpose of demonstration, this Web part implements a pair of GO buttons,one using the JavaScript method and the other using the URL redirection method (bothare valid methods that are easy to use for searching). The other methods mightbe used if you were writing your own search results page or wanted to changethe way search results were returned.

 

With client-side JavaScript, you can use the built-infunctions provided with the SharePoint JavaScript library. The function we wantto use, GoSearch, is located in the search.js library. There are a number ofparameters you can pass to the function. The only parameter the GO button usesis the queryString value retrieved from the option selected in the dropdownlist. As you can see in Figure 7, there are a few hard-coded assumptions, suchas the location of the Search Centerpage and that the desired search scope is ?All Sites?.

 

searchResultsButton = new Button();

searchResultsButton.Text = " GO ClientSide";

searchResultsButton.OnClientClick =

 "GoSearch(null,'" + ddlTopChoicesClient.UniqueID

                   +"',null,true,false,null,'null',null"

                   +",null,'\u002fsearchcenter\u002fPages\u002fResults.aspx'"

                   +", 'This Site','This List', 'This Folder', 'Related Sites'"

                   +", '\u002f_layouts\u002fOSSSearchResults.aspx');";

this.Controls.Add(searchResultsButton);

Figure 7: Create aclient-side search button.

 

Once the JavaScript function is constructed, attach thestring to the OnClientClick event of the button. This will perform the querysearch using the client redirect and will not require that the server have apostback for every request to the search query.

 

The second GO button performs the search on the server. Possiblereasons for using this method would be to modify the URL or to log event informationevery time a user uses the Top Search Query functionality. To perform theserver-side URL redirect, you must create a new dropdown list that has the URLpre-built from the data of the TopSearch control. To create the new dropdowncontrol, loop through each row of the DataTable and construct the URL as{resultsUrl}?k={queryString}&s={scope}. The URL along with parameters forthe queryString and scope are then passed to the correct URL for processing. Asyou can see, a single letter is used for the parameter locations: k is forqueryString; s is for scope. Now when the user presses the button, a server-siderequest is made, processing can be performed, and the redirect to the URLoccurs.

 

Go Directly to BestBet

We?re sure that everyone has seen the functionality onGoogle that lets you go directly to the most relevant search result of thekeyword entered. What if there was the same ability in a SharePoint site? Nowthere can be! Using the search results, keywords, and best bets, here?s a lookat how to create just such a Web part for the users.

 

The first step is connecting to the SharePoint ObjectModel and getting a reference to the Keywords class. The Keywords classcontains a field named Term that can be matched to the search query. Note thatwith this method, all the words in the search string must also be in the Termvalue of the Keyword. Once you have a reference to the Keywords for the site,you can then perform standard operations like Add, View, Create, and Delete. EveryKeyword can have a set of objects, called BestBets, associated with the Keywordterm. These best bets provide a title and URL that can be used to navigatebased on the Keyword term. This section of the article describes how tonavigate directly to the top best bet if someone clicks the I might be Lucky!button.

 

Creating a new button is straightforward; simply create anew button that has a server-side event and when the user clicks the button,search through the keywords to find the right set and redirect the user to thetop best bet. Keyword terms are not based on search scopes like the other querystring results; for that reason, use the first dropdown list you created thathas the query string as the value to make it easy to perform look-ups. Once youhave the query string, there are built-in functions to help you narrow thecollection of keyword results. The Keywords class has a function namedFilterKeywords that takes three parameters. The first two are enumerationsbased on how you want the results returned and the last one is the keyword termyou are looking for ? in this case, it?s the query string search.

 

Now that you have the keyword collection of terms thatmatched the search, you can perform a loop through each keyword. Each keywordmay or may not have a set of best bets associated with it, so you might have tolook at more than one keyword to find the first best bet. Once you find thekeyword with a best bet, get the URL from the best bet and direct the user tothe best bet location. If you don?t find a best bet, you can take the user toanother page or simply notify the user that no best bets are available for thatterm. Figure 8 shows the code that will perform the look-up of the best bet.

 

void bestBetButton_Click(object sender, EventArgs e)

{

 SearchContext searchContext=

SearchContext.GetContext(SPContext.Current.Site);

   Keywords keywords = newKeywords(searchContext, new Uri(SPContext.Current.Site.Url));

 

 KeywordCollection kwc =keywords.GetFilteredKeywords(KeywordView.AllKeywords,

                                                      KeywordFilter.Keyword,

                                                      ddlTopChoicesClient.SelectedValue);

 foreach (Keyword kw inkwc)

 {

     foreach (BestBet bbin kw.BestBets)

     {

         Page.Response.Redirect(bb.Url.ToString());

         return;

     }

 }

 

 lblUserMsg.Text ="No BestBet defined for search query.";

}

Figure 8: Redirectto SharePoint BestBet.

 

Conclusion

There are many ways to extend search with SharePoint. Youcan create custom search results with XSLT, connect to many other systems withBusiness Data Catalog (BDC), and search through files in your enterprise likefile shares. But there is one constant ? users need a way to help them navigatethrough a system. Building tools that use the abilities of enterprise searchcan help direct users to the right information on your site, making it morevaluable as a tool to all users. Building tools that use the usage data andsearch information provide a start to what you can add for your users. Usingadditional capabilities like keywords and best bets will help you, as contentowner, direct your users to relevant information; now you can even see theareas that people are using the most.

 

Search doesn?t have to be just building pages that returnresults, although the Web services provided by Microsoft will allow you tocreate these pages. The real advantage is using all the tools, such asJavaScript, URL navigation, the SharePoint object model, and more to create thesolution that is right for your organization. You can even perform theseactions from other pages or applications by creating an interface, such as a Webservice. Be sure to configure security requirements on any data that youexpose!

 

Building controls that take advantage of the work that hasbeen done by the framework can help you make an impact quickly, but keep inmind that undocumented features can change in the future. For this reason, makesure to test your customizations when you apply service packs and performupgrades.

 

This concludes the exploration of SharePoint Search. This serieshas demonstrated how to correctly configure SharePoint Search on a MOSS 2007portal with a variety of content sources and search scopes. You?ve taken extrasteps to ensure that your users are finding the most relevant details byidentifying best-bet results for certain search terms. You know where to lookto gain insight into how search is being used through a variety of built-inreporting pages. To further your understanding of how search data is stored andtracked, you?ve used Reflector to dive into the guts of SharePoint source codeto discover its hidden secrets. Finally, you?ve applied this knowledge tocreate a custom Web part, which uses the portal itself to keep its contentsfresh and relevant.

 

The source code accompanyingthis series is available for download.

 

Matthew S. Ranlett,a senior consultant with Intellinet?s Information Worker team, is based out of Atlanta.A Microsoft SQL Server MVP, Matt is co-author of ProfessionalSharePoint 2007 Development, and co-founder of the Atlanta.NET Regular Guys, hosted at DevCow (http://www.devcow.com).

 

Brendon Schwartz is a principal consultant with Slalom Consultingin Atlanta specializing inSharePoint 2007. Brendon is a Microsoft MVP, co-author of Professional SharePoint 2007 Development, andco-founder of the Atlanta .NETRegular Guys, hosted at DevCow (http://www.devcow.com).

 

 

 

Add a Comment

There are no comments to display. Be the first one!
You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement




Comments from the DevConnections Community

Join our community of development pros.

Windows problem

I all, I have a problem on my Windows Vista that began afetr the purchase of an external Hard Disk Freecom. A few days afetr the purchase I discon...

Most Recent Posts

GOOGLE LINKS
SPONSORED LINKS
FEATURED LINKS