Step 2: Add the Code for the Custom Search Web Part
The custom search Web Part described in this walkthrough constructs a SQL syntax search query based on user input, and submits it to the Enterprise Search component. The Web Part then converts the search results into XML, and applies an XSLT transformation to display the results in the browser.
Step 2 describes the code you must add for the Web Part.
Note
The XSLT transformation is addressed in Step 3: Create the XSLT Transformation Code.
To modify the default code in SearchProducts
Add the following namespace directives near the top of the code in SearchProducts.cs.
using System.Web.UI.WebControls.WebParts; using Microsoft.Office.Server.Search.Query; using Microsoft.SharePoint; using System.Data; using System.Xml; using System.Xml.Xsl; using System.IO;
In the following code line, replace WebControl with System.Web.UI.WebControls.WebParts.WebPart.
public class SearchProducts : WebControl
Add the following line of code above the class declaration for SearchProducts.
[XmlRoot(Namespace = "SearchBDCWebPart")]
You are now ready to write the code to query the search component, and then render the contents of the Web Part.
To add the Web Part's child controls and render them
Add the following code below the class declaration.
Table table; Label lblID; TextBox txtID; CompareValidator checkID; Label lblName; TextBox txtName; Button cmdSearch; Label lblResults; Xml xmlResults; Panel xmlPanel;
Override the CreateChildControls method by using the following code.
protected override void CreateChildControls() { Controls.Clear(); //Create a table control to use for positioning the controls table = new Table(); table.Width = Unit.Percentage(100); for(int i =0; i<5; i++) { TableRow row= new TableRow(); TableCell cell = new TableCell(); row.Cells.Add(cell); table.Rows.Add(row); } //Create the controls for ProductID input lblID = new Label(); lblID.Text = "Product ID is:"; lblID.Width = Unit.Pixel(150); txtID = new TextBox(); txtID.ID = "txtID"; /* The CompareValidator control is used here to validate that the value entered for ProductID is an integer */ checkID = new CompareValidator(); checkID.ControlToValidate = "txtID"; checkID.Operator = ValidationCompareOperator.DataTypeCheck; checkID.Type = ValidationDataType.Integer; checkID.Text = "ProductID must be an integer."; //Add the controls for the ProductID to the table table.Rows[0].Cells[0].Controls.Add(lblID); table.Rows[0].Cells[0].Controls.Add(txtID); table.Rows[0].Cells[0].Controls.Add(checkID); table.Rows[0].Cells[0].Height = Unit.Pixel(40); //Create the controls for Product Name input. lblName = new Label(); lblName.Text = "Product Name contains:"; txtName = new TextBox(); //Add the controls for the Product Name to the table table.Rows[1].Cells[0].Controls.Add(lblName); table.Rows[1].Cells[0].Controls.Add(txtName); table.Rows[1].Cells[0].Height = Unit.Pixel(40); //Create the search button and add to the table control cmdSearch = new Button(); cmdSearch.Click += new EventHandler(cmdSearch_Click); cmdSearch.Text = "Search Products"; table.Rows[3].Cells[0].Controls.Add(cmdSearch); table.Rows[3].Cells[0].Height = Unit.Pixel(40); //Create a label to display the search message lblResults = new Label(); table.Rows[4].Cells[0].Controls.Add(lblResults); table.Rows[4].Cells[0].Height = Unit.Pixel(40); //Add the table to the controls collection }
Add a click event for cmdSearch, using the following code.
void cmdSearch_Click(object sender, EventArgs e) { string strName = txtName.Text; string strID = txtID.Text; /* Validate that the user entered something. If not, prompt the user to enter an ID or search term. */ if (strName == "" & strID == "") { lblResults.Text = "You must enter a Product ID or a Product name term for the Product Search."; } else { returnResults(buildSQL(strName, strID)); } }
You are ready to add the code to construct the search query text using the Enterprise Search SQL Syntax Reference.
To construct the full text search query
Add the following code to the ProductSearch class:
private string buildSQL(string stName, string stID) { //This is the scope ID for the AdventureWorks //Business Data Catalog application string BDCscopeID = "4"; //Use the StringBuilder class for the syntax string StringBuilder sbSQL = new StringBuilder(); sbSQL.Append("SELECT ProductName,ProductID,ProductNumber,Path FROM SCOPE() WHERE scope='"); sbSQL.Append(BDCscopeID); sbSQL.Append("'"); if (stName != "") { sbSQL.Append(" AND CONTAINS(ProductName,'"); sbSQL.Append(stName); sbSQL.Append("')"); } if (stID != "") { sbSQL.Append(" AND ProductID="); sbSQL.Append(stID); } return sbSQL.ToString(); }
Now you're ready to add the code to access the Query object model. This code sample uses the Microsoft.Office.Server.Search.Query.FullTextSqlQuery class to execute the search query, passing the SPSite object for the parameter value.
The sample accesses the results in XML format using the WriteXml method of the DataSet class. The results XML is passed to the XML Web control that transforms the XML, using a modified version of the XSLT transformation from the Core Search Results Web Part.
To execute the full text search query
Add the following code to the ProductSearch class:
private void returnResults(string strSQL) { try { /* Create the XML control to use for displaying the results, and the Panel control to use as a container for the XML control. */ xmlPanel = new Panel(); xmlResults = new Xml(); xmlPanel.Controls.Add(xmlResults); Controls.Add(xmlPanel); HttpContext context = HttpContext.Current; //Specify the path for the XSL string path = context.Request.MapPath("/_layouts/productXSL.xsl"); //Replace <siteName> with the name of your site string sPath = "http://<siteName>"; FullTextSqlQuery sqlQuery = new FullTextSqlQuery(new SPSite(sPath)); //Specify result type to return sqlQuery.ResultTypes = ResultType.RelevantResults; //Specify the full text search query string sqlQuery.QueryText = strSQL; //Return the search results to a ResultTableCollection ResultTableCollection results = sqlQuery.Execute(); //Create a ResultTable for the relevant results table ResultTable relResults = results[ResultType.RelevantResults]; //Count the number of rows in the table; 0 = no search results int x = relResults.RowCount; if (x !=0) { lblResults.Text = x.ToString(); DataTable dtresults = new DataTable(); dtresults.TableName = "Result"; dtresults.Load(relResults, LoadOption.OverwriteChanges); StringWriter writer = new StringWriter(); DataSet ds = new DataSet("All_Results"); ds.Tables.Add(dtresults); ds.WriteXml(writer, XmlWriteMode.IgnoreSchema); XmlDocument doc = new XmlDocument(); doc.LoadXml(writer.ToString()); XslTransform trans = new XslTransform(); trans.Load(path); xmlResults.Document = doc; xmlResults.Transform = trans; } else { //Send XML for an empty result set to the XML control XmlDocument doc = new XmlDocument(); doc.LoadXml("<All_Results></All_Results>"); XslTransform trans = new XslTransform(); trans.Load(path); xmlResults.Document = doc; xmlResults.Transform = trans; } } catch (Exception ex1) { lblResults.Text = ex1.ToString(); } }
You can find the complete code for the SearchProducts class sample in Sample: AdventureWorks Search Web Part Class Sample Code.
See Also
Tasks
Walkthrough: Creating an ASP.NET Web Part for the AdventureWorks Business Data Application Sample
Step 1: Set Up the Project for the Custom Search Web Part
Step 3: Create the XSLT Transformation Code
Step 4: Deploy the Custom Search Web Part
Step 5: Testing the Search BDC Web Part