GSA (Google Search Appliance) Suggest using C# and jQuery

The Google Search Appliance (GSA) is a search box (a server) that you buy which contains basically the complete search engine from Google. Using this search box allows you to apply the magical Google search results on your intranet, extranet or internet.

The GSA comes with a fully customizable frontend so it will act as a stand-alone machine. But in one of my recent projects we integrated the search results into the customer internet site using a ListView that reads search results in XML format from the GSA and formats it to nice HTML.

Furthermore we implemented the Google Query Suggestion Service on the search box, allowing us to display search suggestions:

GSA Suggestions

GSA Suggestions

Here is what you need. First of all you need to use jQuery. Then you need to download the Ajax Autocomplete for jQuery that implements the autocomplete feature for any input box. The Autocomplete Javascript reads JSON from an .ashx page. So our task is to create an .ashx page that reads suggestions from the GSA and returns them as JSON.

The HttpHandler looks like this (code is sample code. You should apply your own error handling and comments):

namespace GoogleSearchAppliance
{
  public class Suggest : IHttpHandler
  {
    public bool IsReusable
    {
      get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
      if (string.IsNullOrEmpty(context.Request.QueryString[_QUERY_PARAM]))
        throw new Exception(string.Format("Could not find parameter '{0}'", _QUERY_PARAM));
     
      // Get the suggestion word from the parameter
      string suggestiveWord = context.Request.QueryString[_QUERY_PARAM];
      // Create an URL to the GSA
      UrlString suggestionUrl = SuggestionUrl(suggestiveWord);
      // Call the GSA and get the GSA result as a string
      string page = GetPageAsString(suggestionUrl);
      // Convert the GSA result to Json
      string jSonResult = ConvertToJson(page);
      // Return the JSON
      context.Response.Write(jSonResult);
      context.Response.End();
    }

    private string SuggestionUrl(string suggestiveWord)
    {
       // You should modify this line to connect to your
       // own GSA, using the correct collection and frontend
       return "http://myGSAurl/suggest?site=default_collection&client=default_frontend&access=p&format=rich&q" + suggestiveWord;
    }

    private string GetPageAsString(string address)
    {
      // Add your own error handling here
      HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
      using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
      {
        StreamReader reader = new StreamReader(response.GetResponseStream());
        return reader.ReadToEnd();
      }
    }

    private string ConvertToJson(string gsaSuggestResult)
    {
      bool isFirst = true;
      StringBuilder sb = new StringBuilder();
      sb.Append("{ query:");
      foreach (string token in ParseGsaInput(gsaSuggestResult))
      {
        if (isFirst)
        {
          sb.AppendFormat("'{0}', suggestions:[", token.Trim());
          isFirst = false;
        }
        else
        {
          sb.AppendFormat("'{0}',", token.Trim());
        }
      }
      sb.Remove(sb.Length-1, 1);
      sb.Append(@"]}");
      return sb.ToString();
    }
   
    private IEnumerable<string> ParseGsaInput(string gsaSuggestResult)
    {
      gsaSuggestResult = gsaSuggestResult.Replace("[", "").Replace("]", "").Replace("\"", "");
      return gsaSuggestResult.Split(',');
    }

    private const string _QUERY_PARAM = "query";
  }
}

With the HttpHandler in place it is really (really) easy to hook up the code on the input box. Remember to include jQuery and the jquery.autocomplete.js on your page. This is an example code where I assume that the HttpHandler I created is called Suggest.ashx and is placed in the root of my project:

<script language="javascript" type="text/javascript">
  var options, a;
  $(function() {
    options = { serviceUrl: '/Suggest.ashx'};
    a = $jQuery('.metaInput').autocomplete(options);
  });
</script>
<asp:TextBox ID="gssQuery" runat="server" size="31" CssClass="metaInput" Text="Google Site Search"/>

The Autocomplete has some CSS that is applied:

.autocomplete-w1 { position:absolute; top:0px; left:0px; margin:6px 0 0 6px; /* IE6 fix: */ _background:none; _margin:1px 0 0 0; }
.autocomplete { border:1px solid #999; background:#FFF; cursor:default; text-align:left; max-height:350px; overflow:auto; margin:-8px 6px 6px -9px; /* IE6 specific: */ _height:350px;  _margin:0; _overflow-x:hidden; }
.autocomplete .selected { background:#F0F0F0; }
.autocomplete div { padding:2px 5px; white-space:nowrap; overflow:hidden; }
.autocomplete strong { font-weight:normal; color:#CC3333; }
About these ads

About Brian Pedersen

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, c#, General .NET and tagged , , , , , , . Bookmark the permalink.

11 Responses to GSA (Google Search Appliance) Suggest using C# and jQuery

  1. Jaco says:

    Nice article, thanks! One thing I do not understand is why you specifically used a handler for this. Couldn’t you just as easily have created an ASPX page with the same logic?

  2. briancaos says:

    Yes I guess I could. The handler is no more than a light weight ASPX page. I just thought that a handler is more appropriate in this situation.

  3. Rasmus Lohals says:

    Hi Brian,

    Excellent walkthrough you have provided there. I am actually about to implement GSA search results into our existing frontend (ASP.NET 2.0). I am looking through my options for implementing the suggest feature, and was actually considering using the javascript “client” found in the ss.js file found on the GSA, together with asynschronous calls to a page method or a web service to get the suggestions from the GSA. However, your example seems much more elegant and simple. Did you consider using the ss.js from the GSA instead of using the jquery framework?

  4. briancaos says:

    I did try the ss.js but for some reason it would not work in my .net framework.
    This solution is a bit less bound to the GSA as well, so leaving Google requires only changes to the HttpHandler.

  5. srujan says:

    Can you please help me resolving the issue below?
    Error: The type or namespace name ‘UrlString’ could not be found (are you missing a using directive or an assembly reference?

  6. briancaos says:

    Oops. That’s an reminiscence from my Sitecore implementation. The UrlString is a URL string builder class included in Sitecore. Just replace UrlString with a string, as it’s not needed in this example.

    // Create an URL to the GSA
    string suggestionUrl = SuggestionUrl(suggestiveWord);
    // Call the GSA and get the GSA result as a string
    string page = GetPageAsString(suggestionUrl);
    // Convert the GSA result to Json
    string jSonResult = ConvertToJson(page);
    // Return the JSON
    context.Response.Write(jSonResult);
    context.Response.End();

  7. Alex says:

    Thanks. but if you use a custome template and parse the xml what would be the client?, because suggest rest api is expecting that parameter. I appreciate if you can let me know.

  8. Rahul says:

    We implemented the same solution. It working fine for English site but not for other language ( French and Spanish).

    Please help !

  9. briancaos says:

    Give it a couple of hours (or maybe even days) and they will start to pop up.
    The suggest engine runs in low priority.

  10. dinesh says:

    Hi may i get sample code for this. as my code is giving error while calling the ashx file from jquery function. object expected.

  11. Mosab says:

    I faced a problem when parsing the result from ashx file into json. By the way, I think the documentation for this plugin is not complete because it says that the ashx file shoud return a json result of the form:
    {
    query:’Li’,
    suggestions:['Liberia', 'Libyan Arab Jamahiriya', 'Liechtenstein', 'Lithuania'],
    data:['LR', 'LY', 'LI', 'LT']
    }

    but it is far from valid json format. so it gives me errors when parsing.

Leave a Reply

Fill in your details below or click an icon to log in:

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