Thursday, November 10, 2011

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. Using a web service or page method is much 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.

No comments:

Post a Comment