Search autocomplete with ASP.NET AJAX Extensions


I am working on a rich content app for one of my talks at TechEd Europe and I thought it would be a good idea to implement a search box with an autocomplete of the past search quires. The intuition here is that the changes are someone else has searched for the same thing you are searching for, so past queries is an interesting set of options to offer. Not to mention it is fun to look at what other people are searching for 😉 What I think is cool about this is I was able to implement it with less than 10 lines of code and absolutely no database specific logic. I did this with a combination of the ASP.NET 2.0 profile store and the ASP.NET AJAX AutoCompleteExtender…


Here is an example screenshot and all the code\markup required… I’d love to hear what you think… do you think this makes for a compelling demo?



Html for search box and “submit” link (default.aspx)


<div id=”links”>
   Search for
   <asp:TextBox ID=”searchtext” runat=”server” CssClass=”searchbox” />&nbsp;
   <asp:LinkButton ID=”LinkButton1″ runat=”server” OnClick=”LinkButton1_Click”>go</asp:LinkButton><br />
</div>


ASP.NET handler for the LinkButton (default.aspx)


protected void LinkButton1_Click(object sender, EventArgs e)
{
  
StringCollection list = Profile.SearchTerms;
  
if (!list.Contains(searchtext.Text))
  
{
     
list.Add(searchtext.Text);
  

   //TODO: Do search
}


ASP.NET AJAX goodness (default.aspx)


<asp:ScriptManager ID=”ScriptManager” runat=”server” />
<asp:AutoCompleteExtender ID=”AutoCompleteExtender1″ TargetControlID=”searchtext”
                         
runat=”server” ServiceMethod=”GetCompletionList”
                         
ServicePath=”~/SearchAutoComplete.asmx” MinimumPrefixLength=”1″ />


 


Web Service Implementation (SearchAutoComplete.asmx)


[WebMethod]
public string[] GetCompletionList(string prefixText, int count)
{
  
StringCollection list = (StringCollection)HttpContext.Current.Profile[“SearchTerms”];
  
List<string> suggestions = new List<string>();
  
foreach (string s in list)
  
{
     
if (s.StartsWith(prefixText))
     
{
        
suggestions.Add(s); 
      
}
  
}
  
return suggestions.ToArray();
}


Profile Config Section – (Web.config in <system.web> )


<profile>
  
<properties>
     
<add name=SearchTerms
          
type=System.Collections.Specialized.StringCollection
          
serializeAs=Xml /> 
    
</properties>
</profile>


Exercises left for the user



  • Clean up any bad or misleading search terms

  • Sort hits by relevance

  • Add a hit count

  • Age out older results

screenshot.jpg

Comments (28)

  1. Michiel says:

    Nice and simple example. No hassle with db backends to store and retrieve the searched items, simply use the profile functionality. Looks good.

  2. Ross D says:

    I thought profile would be user specific – so would this show you what other people have searched for?

  3. ikrima says:

    Can this method applied to a dropdown box which is read it’s data from sqlserver ????

    for example for dropdown get the customers name

  4. Paolo says:

    The article could be good if only the AutoCompleteExtender existed! It seems to have been removed from the standard ASP.NET Ajax suite (it was there with Atlas). Where did it go?!?

  5. Daniel says:

    One thing I’d like to see addressed is cases where the auto-complete needs additional information displayed in the drop down, but not inserted into the textbox.  For example, Google’s autocomplete tells you about how many results to expect.   Another example- I have several apps that allow a free-text search against a database of people.  Users can begin typing a first name, last name, employee Id, and a few other properties.  Ideally it would drop down a full description "1234 – John Doe – Marketing",  but in the end populate the textbox with only "1234".   This could probably be done with the other AJAX controls, but it seems like using a Name/Value pair instead of a StringCollection would be really useful.

  6. BradA says:

    Ross D – You are right, this is per user search results today…

    ikrima – Yes, of course you can call against a database!  Just change the implementation in the GetCompletionList() method to call against the database…

    Paolo – Sorry, I should have mentioned, AutoCompleteExtender is in the Value-add CTP (http://www.microsoft.com/downloads/details.aspx?FamilyId=8A3FD0DD-D75E-4249-86DA-3D4AAC649652&displaylang=en)    It will be moved to the control toolkit very soon.

    Daniel – Yes, I have some ideas for how to do that… let me play around with it…

  7. Nate says:

    I get this error message.  Any ideas?  

    Compiler Error Message: CS0246: The type or namespace name ‘StringCollection’ could not be found (are you missing a using directive or an assembly reference?)

    Source Error:

    Line 27:     public string[] GetCompletionList(string prefixText, int count)

    Line 28:     {

    Line 29:         StringCollection list = (StringCollection)HttpContext.Current.Profile["SearchTerms"];

    Line 30:         List<string> suggestions = new List<string>();

    Line 31:         foreach (string s in list)

  8. Chris says:

    I too would love to see some more advanced autocomplete usage beyond the basic usage thats been around for some time. Hoping to see that in the demo.

    Besides the drop/down containing more info like Daniel mentioned, I’d like to be able to populate more than one textbox with the choice. So the server needs to be able to send back more than just strings.

    I also need to send the server more information than the current text to generate the list of relevant results to show. That would be great to see.

  9. Brian says:

    There seems to be a bug in the autocomplete extender if you hit enter in the textbox with the textbox empty, it comes up with a javascript error: _completionListElement.childNodes[…].firstChild is null or not an object.

  10. Brad Abrams からです。 Search autocomplete with ASP.NET AJAX Extensions 少し前の投稿ですが、Brad さんが AJAX Extensions

  11. Kent says:

    I would love to check this out but it is not working.  I have all of the web.config entries, etc.  When I run the ScriptResource.axd?d=… referenced in the page source, I get:

    "Object reference not set to an instance of an object. "

    Stack Trace:

    [NullReferenceException: Object reference not set to an instance of an object.]

      System.Web.UI.Page.DecryptString(String s) +40

    [TargetInvocationException: Exception has been thrown by the target of an invocation.]

      System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) +0

      System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) +72

      System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) +358

      System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +29

      System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +17

      Microsoft.Web.Handlers.ScriptResourceHandler.DecryptString(String s) +210

      Microsoft.Web.Handlers.ScriptResourceHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext context) +346

      System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +154

      System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64"

    I just installed all of the latest components this AM, including the November CTP.

  12. damian says:

    hello,

    Where is AutoCompleteExtender in the Ajax ASP.NET? I have install ASP.NET AJAX Beta 2 an I don’t have this ASP.NET AJAX AutoCompleteExtender:(

    Thank’s for answrs

    damian

  13. damian says:

    hello,

    My problem is unbound;-)

    Here is idea: http://forums.asp.net/thread/1464111.aspx

    Brad Abrams – thank’s for You too.

  14. cc_maxx says:

    where is trouble with it…

    Sys.ArgumentTypeException: Object of type ‘Object’ cannot be converted to type ‘Sys.UI.DomElement’.

    and I see the same problem on this page now, Brad :(

    is that only my problem?

  15. cc_maxx says:

    oh sorry Brad that`s ok  with your page :/

  16. Dave Reed says:

    Here’s a extention of autocomplete that lets you do it w/o a webservice, and lets you access page state so the completion items can vary based on other controls:

    http://weblogs.asp.net/infinitiesloop/archive/2006/11/15/ASP.NET-Ajax-Beta_3A00_-AutoCompleteBehavior-without-a-Web-Service.aspx

  17. Lee Wilson says:

    Nice article – looking forward to more advanced features of auto complete being exploited.

    It might be a good idea to ignore case when using the StartsWith method.

    Also, aswell as System.Collections.Specialized – don’t forget to be using System.Collections.Generic.

    Lee

  18. BarryD says:

    If that works for you does this mean that the current requirement to mark your service [ScriptService] is being abandoned?

  19. Shahzad says:

    >>There seems to be a bug in the autocomplete >>extender if you hit enter in the textbox with the >>textbox empty, it comes up with a javascript >>error: _completionListElement.childNodes>>[…].firstChild is >>null or not an object.

    Just put a span in panel u r using to the panel , which is being assigned to "CompletionListElementID" property

  20. vinu says:

    i am getting this error :Microsoft JScript runtime error: ‘Sys’ is undefined

    any idea

  21. vishal says:

    thanx for sharing information …. its relly cool to use autocompleteextender in my project

  22. jspjayalath says:

    I have implimented above code but.It does not call the web service method

  23. Joao says:

    Is it possible to define the GetCompletionList method NOT as a web service.