Steps:
1. Open VS2008, create a project. Under the Visual C# > Web > ASP.NET Server Control. Name the project CustomSearchWebPart.
2. Add the following references to the project:
- System.Data
- System.XML
- Microsoft.SharePoint
- Microsoft.Office.Server
- Microsoft.Office.Server.Search
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Xml;
using System.Xml.Serialization;
using System.Data;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.Office.Server;
using Microsoft.Office.Server.Search.Query;
namespace CustomSearchWebPart
{
[ToolboxData("<{0}:clsSearchQuery runat=server></{0}:clsSearchQuery>")]
[XmlRoot(Namespace = "CustomSearchWebPart")]
public class clsSearchQuery : WebPart
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
Button cmdSearch;
TextBox txtQueryText;
Label lblQueryResult;
DataGrid grdResults;
4. Create a textbox and a search button, add them to the web part.
protected override void CreateChildControls()
{
Controls.Clear();
txtQueryText = new TextBox();
this.Controls.Add(txtQueryText);
cmdSearch = new Button();
cmdSearch.Text = "Start Search";
cmdSearch.Click += new EventHandler(cmdSearch_Click);
this.Controls.Add(cmdSearch);
lblQueryResult = new Label();
this.Controls.Add(lblQueryResult);
}
5. I am using querystring to render the search result as well, so the page which contains this web part could be called by other pages as well.
protected override void OnPreRender(EventArgs e)
{
if (!Page.IsPostBack)
{
if (Page.Request["k"] != null)
{
txtQueryText.Text = Page.Request["k"].ToString();
}
DoSearch();
}
}
private void DoSearch()
{
if (txtQueryText.Text != string.Empty)
{
keywordQueryExecute(txtQueryText.Text);
}
else
{
lblQueryResult.Text = "You must enter a search word.";
}
}
void cmdSearch_Click(object sender, EventArgs e)
{
DoSearch();
}
6. Use KeywordQuery class to get the search result into a ResultTable. Note here I have specified the search to only return result of the Newsletters search scope.
private void keywordQueryExecute(string strQueryText)
{
KeywordQuery kRequest = new KeywordQuery(ServerContext.Current);
string strQuery = strQueryText;
kRequest.QueryText = strQuery;
kRequest.HiddenConstraints = "scope:" + "\"Newsletters\"";
kRequest.ResultTypes = ResultType.RelevantResults;
ResultTableCollection resultTbls = kRequest.Execute();
if ((int)ResultType.RelevantResults != 0)
{
ResultTable tblResult = resultTbls[ResultType.RelevantResults];
if (tblResult.TotalRows == 0)
{
lblQueryResult.Text = "No Search Results Returned.";
}
else
{
ReadResultTable(tblResult);
}
}
}
7. Load the ResultTable into a DataSet.
void ReadResultTable(ResultTable rt)
{
DataTable relResultsTbl = new DataTable();
relResultsTbl.TableName = "Relevant Results";
DataSet ds = new DataSet("resultsset");
ds.Tables.Add(relResultsTbl);
ds.Load(rt, LoadOption.OverwriteChanges, relResultsTbl);
fillResultsGrid(ds);
}
8. Create a datagrid and add it to the web part. Bind it with the search result.
private void fillResultsGrid(DataSet grdDs)
{
//Instantiate the DataGrid, and set the DataSource
grdResults = new DataGrid();
grdResults.DataSource = grdDs;
//Set the display properties for the DataGrid
grdResults.GridLines = GridLines.None;
grdResults.CellPadding = 4;
grdResults.Width = Unit.Percentage(100);
grdResults.ItemStyle.ForeColor = Color.Black;
grdResults.ItemStyle.BackColor = Color.AliceBlue;
grdResults.ItemStyle.Font.Size = FontUnit.Smaller;
grdResults.ItemStyle.Font.Name = "Tahoma";
grdResults.HeaderStyle.BackColor = Color.Navy;
grdResults.HeaderStyle.ForeColor = Color.White;
grdResults.HeaderStyle.Font.Bold = true;
grdResults.HeaderStyle.Font.Name = "Tahoma";
grdResults.HeaderStyle.Font.Size = FontUnit.Medium;
grdResults.AutoGenerateColumns = false;
HyperLinkColumn colTitle = new HyperLinkColumn();
colTitle.DataTextField = "Title";
colTitle.HeaderText = "Title";
colTitle.DataNavigateUrlField = "Path";
grdResults.Columns.Add(colTitle);
BoundColumn colAuthor = new BoundColumn();
colAuthor.DataField = "Author";
colAuthor.HeaderText = "Author";
grdResults.Columns.Add(colAuthor);
grdResults.DataBind();
Controls.Add(grdResults);
}
9. Handles the ItemDataBound event of the datagrid to perform custom actions. In this case, I replace the url column with something else.
void grdResults_ItemDataBound(object sender, DataGridItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item e.Item.ItemType == ListItemType.AlternatingItem)
{
HyperLink h = (HyperLink)e.Item.Cells[0].Controls[0];
String url = h.NavigateUrl;
if (url.Contains(@"Lists/CompanyList/DispForm.aspx?ID="))
{
url = url.Replace(@"Lists/CompanyList/DispForm.aspx", @"Pages/CompanyProfile.aspx");
h.NavigateUrl = url;
}
}
}
}
}
10. If not strong-named, then you can deploy to the bin:
- Add the CustomSearchWebPart.dll to Inetpub\wwwroot\wss\VirtualDirectories\sitename\bin
- Open the web.config in Inetpub\wwwroot\wss\VirtualDirectories\sitename, add the following to the SafeControls section
- <SafeControl Assembly="CustomSearchWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Namespace="CustomSearchWebPart" TypeName="*" Safe="True" />
11. Create the Web Part definition file. Add the following to a notepad and name it CustomSearchWebPart.dwp:
<?xml version="1.0"?>
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
<Assembly>CustomSearchWebPart, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=null</Assembly>
<TypeName>CustomSearchWebPart.clsSearchQuery</TypeName>
<Title>Custom Search Web Part</Title>
</WebPart>
12. Go to the page where you want to add the web part to, click to add a new web part, click the Advanced Web Part gallery and options, click the browser link and then click import to import the dwp file to the web part gallery, then add it to the page.
Reference: