Ajax-enabled search in Umbraco (using Examine and Razor)

I am about to implement an ajax-enabled search for an Umbraco site. Writing the prototype was quick (and fun) so I thought I’d share it. Here goes:

To make it work I have this search macro (run from my search page template):
Search.cshtml:

<form method="post">
<input type="text" id="searchstring" name="searchstring" value="@Request["searchstring"]"/>
<input type="submit"/>
</form>

<div id="searchresults">
@if (IsPost) {
  @RenderPage("SearchResults.cshtml")
}
</div>
              
<script type="text/javascript">
$(document).ready(function() {
    var content = $('#searchstring').val();
    $('#searchstring').keyup(function() {
        if ($('#searchstring').val() != content) {
            content = $('#searchstring').val();
            $.ajax({
               type: "POST",
               url: "/searchresults",
               data: "searchstring=" + content,
               success: function(msg){
                 $('#searchresults').html(msg);
               }
             });                                                                                      
        }
    });                           
});
</script>

Note that the script is using jQuery, which you will need to reference somewhere on your page.

And this macro to get search results (SearchResults.cshtml):

@using Examine
@using Examine.SearchCriteria
@using UmbracoExamine

@{
  var searchString = Request["searchstring"];
  if (!String.IsNullOrEmpty(searchString))
  {
    var searchProvider = ExamineManager.Instance.DefaultSearchProvider.Name;
    var searchResults = ExamineManager.Instance.SearchProviderCollection[searchProvider].Search(searchString, true);

    foreach (var c in searchResults)
    {
      <div>
        <h3><a href="@umbraco.library.NiceUrl(c.Id)">@c.Fields["nodeName"]</a></h3>
        @if(c.Fields.Keys.Contains("bodyText"))
        {
          var bodyText = c.Fields["bodyText"];
          if (bodyText.Length>100)
          {
            bodyText = bodyText.Substring(0,100);
          }
          <p>@Html.Raw(bodyText)</p>
        }
      </div>
    }
  }
}

And to get the search results for my Ajax post I simply have a template (searchresults):

<%@ Master Language="C#" MasterPageFile="~/umbraco/masterpages/default.master" AutoEventWireup="true" %>

<asp:Content ContentPlaceHolderID="ContentPlaceHolderDefault" runat="server">
 <umbraco:Macro Alias="SearchResults" runat="server"></umbraco:Macro>
</asp:Content>

Important about the Examine configuration

I’m using the ootb provided indexer (same as the backend) for this prototype. That’s easy to start with but not advisable for a real site, since it includes both unpublished and protected content.

Please read this article by Shannon Deminick about Examine and Razor.

Improvements

This works, but there are several areas of improvements which I am about to dive into. Suggestions are more than welcome!

* Better handling for the text change (javascript)
* Nicer display of content (examine / strings)
* Limit number of search results / paging

CoffeScript version of the js code

<script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js"></script>
<script type="text/coffeescript">  
  content = $('#searchstring').val()
  $('#searchstring').keyup ->
   currentContent = $('#searchstring').val()
   if currentContent!=content
     content = currentContent
     $.ajax({  
               type: "POST",
               url: "/searchresults",
               data: "searchstring=" + content,
               success: (msg) ->
                 $('#searchresults').html(msg)
           })
</script>
Advertisements

17 thoughts on “Ajax-enabled search in Umbraco (using Examine and Razor)

  1. Yeah I was actually missing jQuery, your example didn’t mention it and with my limited JavaScript experience it took me while to spot it was jQuery.

  2. Thank you for a great example. I am working on implementing ajax in my website and tried using your example. Am I wrong when I think the that the @if (IsPost) {@RenderPage(“SearchResults.cshtml”)}, is not necessary? I think you are actually updating the text twice, once with the @RenderPage and once with the $(‘#searchresults’).html(msg)?

  3. Hi, thanks for your comment, I should have made a codecomment to clarify that. The IsPost is for regular page posts (when the user clicks the button, or hits enter), and the ajax post is for page posts on keyup, and the ajax is actually posting to another page (url: “/searchresults”)

  4. Hi, I have got a problem with the Razor. I am not able to go to the page created with it and it is giving me a 404 error.
    Any Idea?

  5. So the url:”/searchresults”. If the user is on another page within the website and they do a search not on the “/searchresults” page then the page will redirect, right? I am probably going to do this with multiple droplists as a filter rather than a text box.

    • Hi,

      First of all thanks for such great example. Also let me tell you uptill now I was only working on xslts and custome ASP.net coding using UserControls. I am facing lot of issues in Ajax base search. But after using this my proble is half resolved.

      Remaining problem is
      Currently it is searching throughout the site and display the matches… Is there a way that it search only in specific nodes only?

      Hope there will be some ways to do that… thanks in advance..

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s