CodeSnip: Using the Windows Indexing Service with ASP.NET and C#
 
Published: 24 Mar 2008
Abstract
The Windows Indexing Service is a useful tool for providing web based search facilities. In this code sample, Brett shows how to build a .NET friendly search facility using ASP.NET and C#. He begins with a short introduction and then provides a detailed analysis of the code given at the end of the article.
by Brett Burridge
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 30039/ 35

Introduction

The Windows Indexing Service is used to index files via the file system and allow them to be searched through a set of API's. One popular use of Indexing Services is to provide a website search facility for websites hosted on Internet Information Services (IIS).

This article describes how to use Indexing Services from within ASP.NET using C#. The article is "fully .NET friendly," in that it describes how search results can be retrieved as an ADO.NET DataTable and displayed in a DataGrid (using a GridView would use near identical code to that shown). This allows search results to be manipulated and presented in ways that were not easily possible using classic ASP, such as by making use of the built in data column sorting functionality, and the ability to use paging for the search results.

This article assumes that you know how to use Indexing Services and are familiar with the concepts of creating search catalogs. The code sample assumes that an Indexing Service search catalog called "searchcatalog" has already been set up on your web server.

The code samples will work with Index Server on Windows NT 4.0 systems and Indexing Services on Windows Server 2000/2003/XP systems.

Incidentally, if you want to use Index Server with classic ASP, then read this article: http://aspalliance.com/358_Searching_Index_Server_With_ASP.

Using the Code Sample

There are two source code files shown. The ASP.NET file is called IndexingServiceWithCSharp.aspx. It must be associated with a code behind page called IndexingServiceWithCSharp.aspx.cs.

Note that if you want to use this sample source code to show users a graphical representation of how relevant each search result is to their query, you will need to create a set of images called 1bars.png to 10bars.png inclusive, then put them in an images subfolder. Alternatively, matches may be represented as percentages or omitted altogether.

How the Code Works

The ASP.NET page contains two web controls. A label control called LabelNumberOfResults is used to display the number of search results. It is also used to display an errors encountered during a search.

The page also contains a DataGrid control called DataGridSearchResults. This control is used to display the search results. There are columns within this DataGrid for displaying a document's rank, its title and the date the document was last updated. The title is a hyperlink to the actual document itself.

Note that further columns can of course be added if other document properties need to be displayed. Although a DataGrid is used in this example, other web controls can be useful for displaying search results - in some cases it would be appropriate to use the Repeater control for example.

The sample search does not contain a form for a user to enter a search query - for now the query is held within the C#'s QueryText string variable. This value could of course be assigned using the value of a textbox.

The name of the Indexing Service search catalog is contained in the CatalogName variable.

The document rank returned by the Windows Indexing Service has a value of between 0 and 1000 (with 1000 being the most closely matching document). The sample C# code reduces this to a figure between 0 and 10, which then allows the rank of each document to be shown graphically through a set of images with the filenames 0bars.png to 10bars.png inclusive.

Ordering Search Results

It is useful to be able to order search results. One way of achieving this would be to create a DataView from the search results data, and use that to populate the DataGrid:

Listing 1

//Create a DataView from the search results data
DataView SearchDataView = new DataView(SearchResultsTable.Tables[0]);
//Sort the search results by rank
SearchDataView.Sort = "PageRank DESC";
DataGridSearchResults.DataSource = SearchDataView;

Finally, if you are interested in extending the functionality of Indexing Services to allow content on any web server or ODBC database to be indexed and searchable, then take a look at the Indexing Service Companion utility I wrote: http://www.winnershtriangle.com/w/Products.IndexingServiceCompanion.asp.

Source Code

The source code of the ASP.NET page IndexServer.aspx:

Listing 2

<%@ Page language="c#" Codebehind="IndexServer.aspx.cs" AutoEventWireup="false" 
Inherits=" ASPAlliance.IndexServer" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
      <HEAD>
            <title>Indexing Service Test</title>
            <meta name="CODE_LANGUAGE" Content="C#">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta name="vs_targetSchema" 
                content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body MS_POSITIONING="FlowLayout">
            <form id="Form1" method="post" runat="server">
                  <asp:Label id="LabelNumberOfResults" runat="server"></asp:Label>
                  <p><asp:DataGrid id="DataGridSearchResults" runat="server" 
                         HeaderStyle-Font-Bold="True" AutoGenerateColumns="False"
                         BorderWidth="0" AllowCustomPaging="True">
                         <Columns>
                             <asp:BoundColumn DataField="RankImageHTML" 
                                 HeaderText="Rank" />
                             <asp:HyperLinkColumn DataTextField="DocumentTitle" 
                                 DataNavigateUrlField="DocumentURL" 
                                 HeaderText="Document Title" />
                         <asp:BoundColumn DataField="DocumentDate" 
                             HeaderText="Last Updated" />
                         </Columns>
                         </asp:DataGrid></p>
            </form>
      </body>
</HTML>

The source code of the code behind page IndexServer.aspx.cs:

Listing 3

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;
using System.Data.SqlClient;
 
namespace ASPAlliance
{
    /// <summary>
    /// Summary description for IndexServer.
    /// </summary>
    public class IndexServer : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.DataGrid DataGridSearchResults;
        protected System.Web.UI.WebControls.Label LabelNumberOfResults;
 
        private void Page_Load(object sender, System.EventArgs e)
        {
            //The search string
            string QueryText = "asp alliance";
            //The name of your Index Server catalog
            string CatalogName = "searchcatalog"; 
            int NumberOfSearchResults = 0;
            DataSet SearchResults = new DataSet();
 
            //Prevent SQL injection attacks - further security 
            //measures are recommended
            QueryText = QueryText.Replace("'""''");
 
            //Build the search query
            string SQL = "SELECT doctitle, vpath, Path, Write, Size, Rank";
            SQL += "FROM \"" + CatalogName + "\"..SCOPE() ";
            SQL += "WHERE";
            SQL += " CONTAINS(Contents, '" + QueryText + "') ";
            SQL += "AND NOT CONTAINS(Path, '\"_vti_\"') ";
            SQL += "AND NOT CONTAINS(FileName, '\".ascx\" OR";
            SQL += " \".config\" OR \".css\"') ";
            SQL += "ORDER BY Rank DESC";
 
            //Connect to Index Server and perform search query
            try
            {
                OleDbConnection IndexServerConnection = new 
                    OleDbConnection("Provider=msidxs;");
                OleDbCommand dbCommand = new 
                    OleDbCommand(SQL, IndexServerConnection);
 
                OleDbDataAdapter IndexServerDataAdapter = new 
                    OleDbDataAdapter();
                IndexServerDataAdapter.SelectCommand = dbCommand;
 
                IndexServerDataAdapter.Fill(SearchResults);
                NumberOfSearchResults = SearchResults.Tables[0].Rows.Count;
            }
            catch (Exception ExceptionObject)
            {
                //Query failed so display an error message
                NumberOfSearchResults = 0;
                LabelNumberOfResults.Text = 
                    "Problem with retrieving search results due to: " + 
                    ExceptionObject.Message;
                DataGridSearchResults.Visible = false;
 
            }
 
            //Build a datatable for search results
            DataTable SearchResultsTable = new DataTable("SearchResults");
            SearchResultsTable.Columns.Add(new 
                DataColumn("DocumentRank", typeof(int)));
            SearchResultsTable.Columns.Add(new 
                DataColumn("RankPercentage"typeof(int)));
            SearchResultsTable.Columns.Add(new 
                DataColumn("RankNumber"typeof(int)));
            SearchResultsTable.Columns.Add(new 
                DataColumn("RankImageHTML"typeof(String)));
            SearchResultsTable.Columns.Add(new 
                DataColumn("DocumentURL"typeof(String)));
            SearchResultsTable.Columns.Add(new 
                DataColumn("DocumentTitle"typeof(String)));
            SearchResultsTable.Columns.Add(new 
                DataColumn("DocumentDate"typeof(String)));
 
            if (NumberOfSearchResults > 0)
            {
                LabelNumberOfResults.Text = NumberOfSearchResults + 
                    " document(s) were found matching the query '" + 
                    QueryText + "'";
 
                foreach (DataRow SearchResultDataRow in 
                    SearchResults.Tables[0].Rows)
                {
 
                    //Determine the document's date
                    DateTime DocumentDate;
                    try
                    {
                        DocumentDate = Convert.ToDateTime(
                            SearchResultDataRow["Write"].ToString());
                    }
                    catch
                    {
                        DocumentDate = DateTime.Now;
                    }
 
                    //Determine the document's title
                    string DocumentTitle = 
                        SearchResultDataRow["doctitle"].ToString();
                    if (DocumentTitle.Length < 2)
                    {
                        DocumentTitle = "untitled document";
                    }
 
                    //Determine the document's rank
                    int RankNumber = 0;
                    int DocumentRank = Convert.ToInt32(
                        SearchResultDataRow["Rank"].ToString());
                    int RankPercentage = DocumentRank;
                    RankPercentage = Convert.ToInt32(Math.Round(
                        Convert.ToDouble(RankPercentage / 10), 0));
 
                    if (DocumentRank > 900)
                    {
                        RankNumber = 10;
                    }
                    else if (DocumentRank > 800)
                    {
                        RankNumber = 9;
                    }
                    else if (DocumentRank > 700)
                    {
                        RankNumber = 8;
                    }
                    else if (DocumentRank > 600)
                    {
                        RankNumber = 7;
                    }
                    else if (DocumentRank > 500)
                    {
                        RankNumber = 6;
                    }
                    else if (DocumentRank > 400)
                    {
                        RankNumber = 5;
                    }
                    else if (DocumentRank > 300)
                    {
                        RankNumber = 4;
                    }
                    else if (DocumentRank > 200)
                    {
                        RankNumber = 3;
                    }
                    else if (DocumentRank > 100)
                    {
                        RankNumber = 2;
                    }
                    else if (DocumentRank > 0)
                    {
                        RankNumber = 1;
                    }
                    else
                    {
                        RankNumber = 1;
                    }
                    string RankingAltTag = RankPercentage + " percent match";
                    string RankImageHTML = "<img src=\"images/" + 
                        RankNumber + 
                        "bars.png\" width=\"80\" height=\"17\" alt=\"" + 
                        RankingAltTag + "\">&nbsp;";
 
                    //Populate a DataRow for the current search result
                    DataRow SearchResultsRow = SearchResultsTable.NewRow();
                    SearchResultsRow["DocumentRank"] = 
                        SearchResultDataRow["Rank"].ToString();
                    SearchResultsRow["RankPercentage"= RankPercentage;
                    SearchResultsRow["RankNumber"= RankNumber;
                    SearchResultsRow["DocumentURL"= 
                        SearchResultDataRow["vpath"].ToString();
                    SearchResultsRow["DocumentTitle"= DocumentTitle;
                    SearchResultsRow["RankImageHTML"= RankImageHTML;
                    SearchResultsRow["DocumentDate"= 
                        DocumentDate.ToString("dd MMMM yyyy");
                    SearchResultsTable.Rows.Add(SearchResultsRow);
                }
 
                //Bind DataTable to DataGrid
                DataGridSearchResults.Visible = true;
                DataGridSearchResults.DataSource = SearchResultsTable;
                DataGridSearchResults.DataBind();
            }
            else
            {
                //No search results were found for the query
                DataGridSearchResults.Visible = false;
                LabelNumberOfResults.Text = 
                    "No document(s) were found matching the query '" + 
                    QueryText + "'";
            }
 
        }
 
        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
        }
 
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.Load += new System.EventHandler(this.Page_Load);
 
        }
        #endregion
    }
}
Conclusion

In this article you have learned how to create a search application with Windows Indexing Service using ASP.NET with the help of a sample code.



User Comments

No comments posted yet.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-29 11:58:18 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search