Bernie Cook's Blog

Azure, C#, .NET, Architecture & Related Tech News

AJAX AutoCompleteExtender/Web.Config Rule Issue

Leave a comment

Last week I was adding the latest AJAX AutoCompleteExtender control (from the November 2011 AJAX Control Toolkit release) and ran into a peculiar problem which I later corrected and thought I’d document.

The updated AJAX AutoCompleteExtender has a lot of appeal, particular with regards to integration – you don’t have to call a separate web service, or a separate AJAX-enabled WCF service, or add entries to your web.config, to populate the AutoCompleteExtender control – all you need is a public static method in your code-behind page. The method signature is provided below:

[WebMethodAttribute(), ScriptMethodAttribute()] 
public static string[] GetCompletionList(
    string prefixText,
    int count, 
    string contextKey)
    // Some code.

Adding the control and it’s associated methods was easy: step 1 drop in the ToolkitScriptManager, step 2 drop in a TextBox, step 3 drop in the AutoCompleteExtender and point it at the TextBox, and step 4 point the extender at a code-behind method (GetCompletionList()) with the appropriate signature and off you go. See Microsoft’s official instructions on the “Creating a Simple Auto-Complete TextBox” page for the particulars.

Anyway I followed the steps, placed a breakpoint in my GetCompletionList() method and ran my project. What happened next was quite unexpected – I would type some characters into my TextBox and then the AutoCompleteExtender’s list of options would appear with a single character displayed in every option. I could tell from the first few characters that the control was displaying an entire HTML page within the options list. Also my breakpoint wasn’t being hit so I suspected that an error was being returned and the underlying error page’s HTML was being pumped out into the list, a very long list.

So I did all the standard things you do when you find a bug; reviewed my code for obvious errors, Googled the issue, created a vanilla project with just the control, etc. until I isolated the problem. To make a long story short the problem was located in a lower casing URL web.config rule I’d added several months prior for better SEO compliance (see “Fix Common SEO Problems Using the URL Rewrite Extension” by Scott Gu for more information – great article by the way). See my code below prior to the fix (this goes under the <system.Webserver><rewrite><rules> node):

<rule name="Lower Case URLs" stopProcessing="true" url="[A-Z]" ignoreCase="false">
    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{URL}" pattern="WebResource.axd" negate="true"/>
        <add input="{URL}" pattern="ScriptResource.axd" negate="true"/>
        <add input="{URL}" pattern=".js" negate="true"/>
    <action type="Redirect" url="{ToLower:{URL}}">

The code-behind page, which contained the GetCompletionList() method, was called “Add.aspx” so all I had to do was add an exception, similar to the WebResource.axd condition, to my rule and voila it worked. For some reason the AutoCompleteExtender’s ServicePath property needs the exact page’s name as it’s called, so prior to my rule’s amendment it was trying to hit “add.aspx” despite it being coded as “Add.aspx”. Perhaps the AJAX Control Toolkit is performing a lookup in the background for a namespace with the matching casing.

As a side IIS still lowercased my “Add.aspx” URLs (as long as they weren’t in the root directory of my web role) so I didn’t have to worry about calls to “Add.aspx” or “add.aspx” being identified as two separate pages by search engines.

Hopefully someone experiencing this same issue finds this post and saves the time that I seemingly “lost” resolving this issue.

Further to this if I had used a WCF service I could have just added a condition which ignored all .svc files.

For completeness I’ve included my  control code below:

<asp:TextBox runat="server" ID="txtFullName" TextMode="SingleLine" MaxLength="200" />
<ajx:AutoCompleteExtender runat="server" ID="ajxAutoCompleteExtender" TargetControlID="txtFullName"
     ServiceMethod="GetCompletionList" ServicePath="Add.aspx"
     CompletionInterval="100" MinimumPrefixLength="2" UseContextKey="True" DelimiterCharacters="" CompletionSetCount="15"/>

Further Reading

Author: Bernie

I currently live and work in the UK, just outside of London. I've been working in IT for 15+ years and in that time have solved many technical problems via blogs, forums, tutorials etc. and feel like I should be giving something back. This blog post is my way of contributing and I hope it proves just as useful to others as their contributions have to me.

Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s