ASP.NET AJAX username availability check

When you have a name as common as mine, you run across the entire gamut of schemes to deal with username availability in membership systems. By availability, of course I mean denial and rejection. Out of all of the ways that I’ve had “Dave” rejected, inline AJAX verification is definitely the least annoying. Wanting to be less-annoying myself, I’ve added the same functionality to my ASP.NET AJAX sites. Let me show you how I did it.

Note: I will preface this example by saying that an UpdatePanel is not the most efficient possible way to solve the problem. Something like this is lighter over the wire. However, for the vast majority of sites, this method is perfectly suitable and much easier to work with.

Setting up the page.

For this example, I’m going to use a very simple registration form:

    Username: <asp:TextBox runat="server" id="Username" /><br />
Password: <asp:TextBox runat="server" ID="Password" /><br />
Confirm: <asp:TextBox runat="server" ID="PasswordConfirm" /><br />
<asp:Button runat="server" ID="Button1" Text="Sign me up!" />

Since I want to work with it asynchronously, I’m going to wrap the Username TextBox in an UpdatePanel. I’m also going to enable AutoPostBacks on it and handle its OnTextChanged event. Inside an UpdatePanel, this will cause a partial postback to the event handler any time the TextBox loses focus and its contents have changed.

<asp:UpdatePanel runat="server" ID="up1">
 <ContentTemplate>
   Username: <asp:TextBox runat="server" id="Username"
   AutoPostBack="true" OnTextChanged="Username_Changed" /><br />
 </ContentTemplate>
</asp:UpdatePanel>

Note that I only wrapped the username line in the UpdatePanel. If the entire form were in an UpdatePanel, the returning partial postback would revert all of the form fields to their values when the postback initiated. That behavior would be undesirable here, where users will likely be tabbing through the form quickly and might complete several other fields during the partial postback.

Checking username availability

I decided to check availability through a call to Membership.GetUser(). If a user with the supplied name exists, the method will return the corresponding MembershipUser. Otherwise, it returns null. With this in mind our OnTextChanged event handler is easy:

protected void Username_Changed(object sender, EventArgs e)
{
 if (Membership.GetUser(Username.Text) != null)
   // Display a username taken message.
 else
   // Display a username available message.
}

This method should work with any .NET Membership Provider setup, regardless of your data store or other customizations. Obviously, if you’re using a custom authentication system instead of the .NET Membership Provider, then you’ll need to perform the availability check a different way.

If anyone knows of a more efficient method for checking the username availability, I’d be interested in hearing it. Returning an entire MembershipUser object to express (in this case) what boils down to a boolean value is painfully wasteful.

Displaying the availability result

I chose to display my message in a div, just to the right of the username field:

<asp:UpdatePanel runat="server" ID="up1">
 <ContentTemplate>
   Username: <asp:TextBox runat="server" id="Username"
   AutoPostBack="true" OnTextChanged="Username_Changed" />
   <div runat="server" id="UserAvailability"></div><br />
 </ContentTemplate>
</asp:UpdatePanel>

With that element now accessible, I can complete the Username_Changed event handler:

protected void Username_Changed(object sender, EventArgs e)
{
 if (Membership.GetUser(Username.Text) != null)
 {
   UserAvailability.InnerText = "Username taken, sorry.";
   UserAvailability.Attributes.Add("class", "taken");
 }
 else
 {
   UserAvailability.InnerText = "Username available!";
   UserAvailability.Attributes.Add("class", "available");
 }
}

The relevant CSS:

#UserAvailability {
 padding-left: 22px;
 background-position: left;
 background-repeat: no-repeat;
}

.taken {
 background-image: url(taken.gif);
}

.available {
 background-image: url(available.gif);
}

The CSS classes, taken and available, are used to display a left positioned background image in the div (as seen in the screenshot above). The left padding ensures that the text message doesn’t overlap the status image. This visual cue is very powerful, and should not be overlooked.

That’s it!(source -http://encosia.com)

Is AutoComplete Extender working

There are numerous blogs and forums discussing that “AutoComplete Extender is not working”. When I had to work on it for one of my clients, I too found that AutoComplete Extender does not work. I followed the steps given in http://ajax.asp.net/ but I was left with the same impression that “AutoComplete Extender is not working” . Anyway try try again till you get gain is the formula I generally adopt. After googling of hours together, I found the solution. Though the solution is given in many forums/blogs, yet you need to give more attention to it to catch the point. So in this blog I tried to highlight the small but the important lines that require more attention. AutoComplete Extender AutoComplete is an ASP.NET AJAX extender that can be attached to any TextBox control, and will associate that control with a popup panel to display words that begin with the prefix typed into the textbox. Following are the steps:- Step 1 : Add autocomplete extender where you want to and configure it as explained in
  
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    <div>
    <asp:TextBox ID="txtSuggest" runat="server" ></asp:TextBox>
   <ajaxToolkit:AutoCompleteExtender runat="server"
ID="AutoCompleteExtender1"
 TargetControlID="txtSuggest"
 Enabled="true"
 MinimumPrefixLength="1"
     ServicePath="WebService.asmx"
ServiceMethod="GetSuggestions"

  />

    </div>
</form>
</body>
</html>
Step 2 : Add the following web service with name "WebService.asmx"and consume it :-
using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;


///
/// Summary description for WebService
///
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class SuggestionService : System.Web.Services.WebService
{

    [WebMethod]
    [System.Web.Script.Services.ScriptMethod]
    public string[] GetSuggestions(string prefixText, int count)
    {
        int i = 0;
        DataView data = GetData();
        data = FilterData(data, prefixText);
        string[] suggestions = new string[data.Count];

        foreach (DataRowView row in data)
            suggestions[i++] = row["FirstName"].ToString();

        return suggestions;
    }

    private DataView GetData()
    {
        DataView view = (DataView)HttpContext.Current.Cache["Suggestions"];
        if (view == null)
        {
            SqlDataAdapter adapter = new SqlDataAdapter(
            "SELECT * FROM addressbook", System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"]
            .ConnectionString);
            DataTable table = new DataTable();
            adapter.Fill(table);
            view = table.DefaultView;

            // Store the entire data set to the ASP.NET Cache for
            // further reuse
            HttpContext.Current.Cache["Suggestions"] = view;
        }

        return view;
    }

    private DataView FilterData(DataView view, string prefix)
    {
        // Filter out undesired strings
        view.RowFilter = String.Format("FirstName LIKE '{0}%'", prefix);
        return view;
    }


}