Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Implement Search Functionality into your ASP.NET MVC Application

0.00/5 (No votes)
21 Sep 2009 1  
This article will demonstrate how to enable searches in your applications. The fact that the ASP.NET MVC framework makes it easier to modularize and componentize your design/code makes it better with minimal effort.

Introduction

It's probably safe to assume that if you are reading this, then you are somewhat connected to the enterprise applications world. Chances are then your apps did, in one form or the other provide search functionality to users. We may have moved from the filters/parameters to a free form ubiquitous search, but the needs remains.

I had a similar need for one of my recent projects – Users wanted a free form “bing” like search that works across the application, consistently and is super responsive.

While I could have done it in a number of ways, the approach we took was to design a re-usable search skeleton design that anyone creating a web app using the ASP.NET MVC Framework can simply plug in with minimal effort and search-enable their application.

I will use a sample contact manager application to demonstrate how to write a skeleton that allows search functionality to be easily integrated into your ASP.NET MVC web site. Before I jump into the code, let's first take a look at the end result so you'll be able to envision what I am trying to accomplish.

In the simplest form, you type the search text you want to find into the text box, select the search category you want to use from the Dropdown List and click the "Search" icon.

clip_image001

Search Flow

clip_image002

Search Panel

When a user types something and clicks on the search icon, the searchClick method will execute.

function searchClick() {
    var category = $("#searchList").val();
    var searchText = $("#txtSearch").val();
    var queryString = "SearchText=" + searchText + "&Category=" + category;
    $.post("/Search/Search", queryString, callBackSearch, "_default");
}

By using $.post (I am using jQuery), we are pointing to my Search controller Search action. It will also allow us to pass the query string. In callBackSearch function, we will embed the return response HTML in the current page.

$('#SearchResult').html(responseText); 

Search Controller

public ActionResult Search(RouteInfo routeValues)
{
  string actionName = "Search";
  string controllerName =                  
         SearchHelper.GetControllerName(routeValues.Category);
  return RedirectToAction(actionName, controllerName, routeValues);
}

SearchHelper.GetControllerName will return the controller name which is responsible for the search result view for a given category.

public static string GetControllerName(string category)
{
 // TODO: Manage thru configuration
 return "Contact";
}

For demo purposes, I am returning a hard coded string “Contact”. In a real scenario, you may need to keep some controller configuration for a different category search. Please change as appropriate.

The Search controller will now redirect to a specific controller search action. In this case, it will call the Contact controller.

Contact Controller

public ActionResult Search(RouteInfo routeValues, 
	SearchCriteriaSubController searchCriteria)
{
  ContactManagerEntities _entitities = new ContactManagerEntities();
  string criteria = SearchHelper.GetSqlCriteria(routeValues.SearchText,
                    routeValues.Category);
  List<contact> contactList = _entitities.GetContacts(criteria).ToList();
  ViewData["contactList"] = contactList;
  return View();
}

Contact controller is responsible for creating the search result view. To get the data for a given search text, we need to create a stored procedure named GetContacts.

ALTER PROCEDURE dbo.GetContacts
      (
      @criteria  NVARCHAR(3000) 
      )
AS
      SET NOCOUNT ON 
      DECLARE @SQLString NVARCHAR(4000);
      SET @SQLString = N'SELECT ID, FirstName, LastName, Phone, Email 
                       FROM Contacts WHERE ' + @criteria ;
      EXECUTE sp_executesql @SQLString
RETURN

If your user types ‘Microsoft’ on the search text, then the criteria which will be passed to this stored procedure will be:

“[FirstName] LIKE '%microsoft%' OR [LastName] LIKE '%microsoft%' 
	OR [Email] LIKE '%microsoft%' “ 

Note: You can maintain your own set of SQL symbol format (LIKE, IN, BETWEEN, =, >, <, etc.). In this demo, I have used contain search functionality. Also you can extend this search helper class to allow user Full Text Search functionality. Click on the following link to get an idea of how to make Google style queries to SQL Server's full-text search CONTAINS predicate syntax.

SQL Criteria Builder

public static string GetSqlCriteria(string searchText, string category)
{
  StringBuilder sb = new StringBuilder();
  // Get the list of columns for this category
  List<searchcolumn> SearchColumns = GetSearchColumns(category);
  bool isFirstRow = true;
  foreach (SearchColumn row in SearchColumns)
    {
      string text;
      // Build the SQL syntax for this column 
      // eg. [FirstName] LIKE '%microsoft%' 
      text = string.Format(row.SymbolFormat, row.ColumnName, searchText);
      if (isFirstRow)
        isFirstRow = false;
      else
        sb.Append(" OR ");
      sb.Append(text);
    }
  return sb.ToString();
}

Once SQL criteria is ready, the contact controller will pass it to dbEntitities GetContacts method to get the search result.

List<contact> contactList = _entitities.GetContacts(criteria).ToList();

Result View

Display Search Criteria using Sub Controller

Since our Search Criteria UI is common for each category search result, I wanted to re-use criteria UI pieces on other pages. I have used sub controller’s action to render the search criteria UI inside the Result view page.

SubController derives from Controller and implements an ISubController interface. But it is a controller, so: 

  • It has its own view. 
  • It has ViewData.
  • It has access to query string and the rest of the controller context.

You can download and explore a complete working sample on SubController from MvcContrib.

Listing SearchCriteriaSubController.cs
public ViewResult SearchCriteria(RouteInfo routeValues)
{
 ViewData["text"] = "SearchText = " + routeValues.SearchText + 
         " and Category = " + routeValues.Category;
 return View();
}
Listing SearchCriteria.ascx

Summary

So to re-iterate, these are the steps you will follow to search enable any other applications:

  1. Create Search Controller 
  2. Create Search Stored Procedure 
  3. Set necessary changes to redirect routing from search controller
  4. Create a Results view

Conclusion

My goal was to demonstrate how simple and straightforward it is to enable searches in your applications. The fact that the ASP.NET MVC Framework makes it easier to modularize and componentize your design/code makes it even better as the platform of choice for Windows based web applications.

We created a working sample app, outlined the search requirements, created a reusable skeleton project that implements the search function and showed how to wire that within your app to search enable it.

That's really all there is to it. For those of you not familiar with ASP.NET MVC and entity framework, the code may seem confusing at first, but once you play with it a little and look at a few samples, I'm sure you'll get the hang of it. For questions/concerns, it would be much appreciated if you can leave a comment on the blog.

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here