Using ASP.NET, Membership, and jQuery to Determine Username Availability
By Scott Mitchell
Chances are, at some point you've tried creating a new user account on a website and were told that the username you selected was already taken. This is especially common on very large websites with millions of members, but can happen on smaller websites with common usernames, such as people's names or popular words or phrases in the lexicon of the online community that frequents the website. If the user registration process is short and sweet, most users won't balk when they are told their desired username has already been taken - they'll just try a new one. But if the user registration process is long, involving several questions and scrolling, it can be frustrating to complete the registration process only to be told you need to return to the top of the page to try a different username.
Many websites use Ajax techniques to check whether a visitor's desired username is available as soon as they enter it (rather than waiting for them to submit the form). This article shows how to implement such a feature in an ASP.NET website using Membership and jQuery. This article includes a demo available for download that implements this behavior in an ASP.NET WebForms application that uses the CreateUserWizard control to register new users. However, the concepts in this article can be applied to ad-hoc user registration pages and ASP.NET MVC.
Read on to learn more!
Step 0: An Overview of Checking Username Availability
Before we dive into how to go about using Ajax techniques to check username availability when creating a new account, let's first take a moment to examine our end goal. The idea here is that when a user is registering a new account and enters their desired username they will be alerted if the username is already in use by another. The demo available for download at the end of this article has a web page named
CreateAccount.aspxthat contains a CreateUserWizard control. By default, the CreateUserWizard control does not preemptively check to see if the desired username is available. Instead, the username availability check is performed when the user clicks the "Create User" button.
The screen shot below shows the CreateUserWizard control when the user first visits the
CreateAccount.aspx page and has not entered any information into the
When the user changes the username to something unique, such as "Scotty", the "This username is already taken!" message is replaced with a short message letting them know that their new username is available.
Note that the "This username is available" message only appears if the user enters an available username after entering an unavailable one. If the user started the process by entering an available username no message is displayed.
Step 1: Creating a Server-Side Service That Reports Username Availability
To determine whether a visitor's desired username is available we need a server-side service that can be invoked from client-side script that reports the availability of a specified username. As discussed in my article series Accessing Server-Side Data from Client Script, there are a variety of ways by which to implement such a server-side service, including using:
- An ASP.NET web page
- A generic HTTP handler
- An ASMX Web Service
- A WCF Service
Servicesfolder and, in there, added a new ASP.NET page named
UsernameAvailable.aspx. This page has no markup defined in its
.aspxfile. Instead, it returns JSON that defines an object with a single Boolean property,
|What Is JSON?|
UsernameAvailable.aspx page expects the desired username to be supplied in the querystring, like so:
UsernameAvailable.aspx?desiredUsername. The page then looks to see if there exists a user with the username desiredUsername and returns an
appropriate JSON payload.
For example, an HTTP request to
UsernameAvailable.aspx?Scott returns the following JSON payload:
false since there already exists a user with the username "Scott". However, if you were to check on the availability of,
say, Alexis -
UsernameAvailable.aspx?Alexis - you'd get back a JSON payload reporting the username is available.
The code for the
UsernameAvailable.aspx page is quite simple and is contained entirely in its
Page_Load event handler. It starts by setting the
Content-Type attribute to
application/json, which is the MIME type for JSON data.
Next, the username is read from the querystring and a string variable named
output is defined.
If a non-empty username was supplied, the Membership system is invoked to see if there exists a user with the desired username. Specifically, the
Membership.GetUser method is called, passing in the desired username. If this method returns a
MembershipUser object then that means that
there exists a user with this username. If the
Membership.GetUser method return
null, in C# parlance) then the username
is available! The output variable is assigned the appropriate JSON payload and this JSON is returned in the request via a call to
Step 2: Customizing the CreateUserWizard Control to Show a "Username Taken" Message
CreateAccount.aspxpage uses the CreateUserWizard control to register a new user account. By default, the CreateUserWizard displays an interface that prompts the user for their username and password, with additional fields for email and a security question and answer if the Membership system is configured to collect this information. However, the CreateUserWizard's user interface can be modified by converting the CreateUserWizard into a template. (To accomplish this, go to the Design view and, from the control's smart tag, click the "Customize Create User Step" link.)
To implement this functionality we need to convert the CreateUserWizard into a template so that we can access its Username textbox from client-side script and so that
we can add the markup to display the "This username is already taken!" message, if needed. Converting the CreateUserWizard control into a template generates a lot of markup.
The most pertinent bit for this discussion is the
UserName TextBox, whose markup I show below. Note that the CreateUserWizard control is in a
and there is a table row (
<tr>) for the username entry.
After converting the CreateUserWizard control to a template, add a table row for the "This username is already taken!" message. As the markup below shows, this table
row has an
usernameUnavailableRow and contains a
<span> element whose
id is set to
We will access and modify these two HTML elements in client-side script if the visitor creating an account enters an unavailable username.
Step 3: Calling the
UsernameAvailable.aspx Service When Entering a Username
The final piece of the puzzle is to call the
UsernameAvailable.aspxservice whenever focus is lost from the
UserNameTextBox. This can be accomplished using jQuery's
getJSONfunction, which takes two input parameters: the URL to request and the function to execute once the data is returned. The data returned is the object defined via the JSON payload - namely, an object with an
availableBoolean property. If
availableis false then we need to show the message "This username is already taken!"
The following jQuery performs these steps. Because this script is in the
$(document).ready event handler it will run when the page is loaded in the browser.
The above code starts by referencing the
usernameUnavailableRow table row (
UserName textbox. The syntax for referencing the
UserName textbox warrants some further discussion.
When we converted the CreateUserWizard control into a template it generated markup that included a TextBox control with its
ID property set to
While the TextBox control's
ID is simply
UserName, its rendered client-side
id attribute turns into something different due to the
fact that the TextBox control is within a template. To determine this value we have two options:
- If you are using ASP.NET 4 or beyond, set the TextBox's
Static. This ensures that the rendered client-side
idattribute matches up precisely with the server-side
IDvalue. See Take Control Of Web Control ClientID Values in ASP.NET 4 for more information on this technique.
- Use server-side code to output the appropriate client-side
idattribute value into the script.
idfor a Web control would be:
<%=webControlId.ClientID %>. However, in this case we have to do a bit more work because the
UserNameTextBox is buried in the CreateUserWizard control's template. Consequently, to get programmatic access to the TextBox we need get to the template itself and then use the
FindControlmethod to dig out the Web control.
IDof the CreateUserWizard control, and its
CreateUserStepproperty returns the wizard control's create user step. The create user step's
ContentTemplateContainerproperty returns the template, which then can be searched via
FindControl. Once we have the TextBox we can get the value of the client-side
idattribute it will render via its
ClientIDproperty. Put it all together and we get:
<%=cuWizard.CreateUserStep.ContentTemplateContainer.FindControl("UserName").ClientID %>. Whee!
After these three HTML elements have been referenced, the
usernameUnavailableRow table row is hidden (by calling
Next, an event handler for the
blur event is created. If there is a value entered into the textbox then jQuery's
getJSON function is called, which makes an asynchronous HTTP request to
Services/UsernameAvailable.aspx, passing the value entered into the
textbox through the querystring.
When the server returns its response, the function defined as the second parameter to
getJSON is invoked. Here, the variable
the JSON object returned by the server. If the
available property is true then we don't need to do anything unless the
table row is visible, in which case we want to update the
<span> element to show the message "This username is available."
usernameAvailable CSS class is added to the
<span> and the
usernameTaken CSS class is removed (if needed).
These two CSS classes are defined in the
Style.css stylesheet and are what makes the message italicized and displayed in a red or black color.
available property is false then the
usernameUnavailableRow table row is displayed (via
<span> element's text and CSS classes are set accordingly.
And... that's it! Putting it all together, we have a customized user registration page and server-side service that work in tandem to seamlessly notify a user if their desired username is unavailable.