Checking the Existence of an ASP.NET Membership Username with ASP.NET AJAX

If you have been using the Membership features that ship with ASP.NET, I'm sure you're familiar with the CreateUserWizard control that lets a user sign up for an account on your site. One of the features of this control (in cooperation with the Membership services) is to check whether a given user name is already taken and display an appropriate message if that's the case. This is an excellent feature as it makes sure no two users can end up with the same user name.

One of the problems with this check is that it takes place at the server. This means the page goes through a full post back which takes some time. Even worse, due to security settings on the control, the two password fields are reset so the user has to enter them again in case they chose an existing user name. It would be a lot easier if you could check the user name before the page is posted back using a bit of client side script. With ASP.NET AJAX and Page Methods, this is a walk in the park.

Create a Client Side User Name Check

You can check the user name at the client using Page Methods. The Page Method is called from the client and then executes some code at the server. The server side method then uses the Membership API to check whether the user name is already taken and returns the value to the client. Writing this functionality takes five steps:

  • Set up a ScriptManager control to allow and handle Page Method calls.
  • Write the Page Method in the page that contains the CreateUserWizard.
  • Add a hidden element (like a span) to the page to hold the error message. Hide the element by default, so it can be shown when the user name already exists.
  • Set up a handler for the UserName text box's blur event.
  • Write some code that is executed when the UserName text box looses focus; the code should call the Page Method and show or hide an appropriate error message.

Setting Up the ScriptManager

If your page is based on a Master Page, you could add the ScriptManager control to that Master Page so it becomes available to all pages in your site. Alternatively, you can add the ScriptManager directly to the page containing the CreateUserWizard. Either way, you need to set the ScriptManager's EnablePageMethods to true:

<asp:ScriptManager ID="ScriptManager1" runat="server" 
               EnablePageMethods="true" />

Write a Page Method that Checks the User Name

To create a Page Method callable from client script, all you need to do is write a static method in the page's code section and apply the WebMethod attribute. To check the existence of the user using the Membership API, the method should accept the proposed user name and return a bool to indicate whether the name exists or not. Your method could look like this:

[WebMethod]
public static bool UserNameExists(string yourName)
{
return Membership.GetUser(yourName) != null;
}

When GetUser returns null, it means the user is not found and the method returns false.

Add the Error Message Label to the Page

There are a number of ways to add the error message to the page. One way is to convert the entire CreateUserWizard to a template using its Smart Task Panel. Then you can add a Label or another element directly in the markup in the ASPX page. Another alternative is to dynamically inject the element at run-time using JavaScript. You can do this in a JavaScript block defined below the CreateUserWizard control like this:

var userNameTextBox = 
   $get('<%= CreateUserWizard1.ClientID %>_CreateUserStepContainer_UserName');
var userNameRequiredMessage = 
   $get('<%= CreateUserWizard1.ClientID %>_CreateUserStepContainer_UserNameRequired');
var errorMessage = document.createElement('span');
errorMessage.style.visibility = 'hidden';
errorMessage.style.color = 'red';
errorMessage.innerHTML = 'User name already taken';
userNameRequiredMessage.parentNode.appendChild(errorMessage);

The first couple of lines of code get a reference to the UserName text box and the error message for the RequiredFieldValidator for the user name. I am using <%= CreateUserWizard1.ClientID %> to get the client side ID of the CreateUserWizard. This is better than hard coding it in the JavaScript as things will break without a compile error if you rename the control. Internally, the UserName control is always called CreateUserStepContainer_UserName so it's OK to hard code that in.

If you were using ASP.NET 4.0, things would be a lot easier. You can set the ClientIDMode to Static which gives the CreateUserWizard a static client ID. This in turn means that the UserName and UserNameRequired elements simply are named UserName and UserNameRequired respectively. This way you can simplify the code to read:

var userNameTextBox = $get('UserName');
var userNameRequiredMessage = $get('UserNameRequired');                  

The remainder of the code creates a new DOM element using document.createElement. It sets the innerText to the error message, changes its font color and then hides the element by setting its visibility to hidden. Finally, the element is injected to the page, right before the existing error message for the required user name using insertBefore. Instead of assigning font and other information to the element directly, you could of course set its className property to refer to some CSS class. Now that the message is injected to the page, it's ready to be used by other code in the page.

Set up a Handler for the User Name text box's blur Event

Setting up the handler to call some code when the user moves the cursor away from the text box is easy. All you need is a single line of code:

$addHandler(userNameTextBox, 'blur', UserNameExists);                  

This method uses the userNameTextBox variable declared earlier and assigns UserNameExists as the method to call when the control looses focus. The final action now is to implement UserNameExists and have it call the Page Method to determine if the user exists or not.

Calling the Page Method to Check Whether the User Exists

To call a Page Method, you call the name of your method on the PageMethods class that ASP.NET AJAX makes available for you. When doing so, you need to define a callback method that is called when the page method returns its answer. Inside this callback you can check the return value of the method call and then hide or show the error message depending on the outcome. The implementation can be as simple as this:

function UserNameExists()
{
  var userName = userNameTextBox.value;
  PageMethods.UserNameExists(userName, UserNameExistsCallback);
}

function UserNameExistsCallback(result)
{
  errorMessage.style.visibility = result ? 'visible' : 'hidden';
}

The UserNameExists JavaScript method calls the UserNameExists Page Method using the PageMethods class and passes it the user name that it retrieves from the userNameTextBox element. When the Page Method returns, the callback method UserNameExistsCallback is executed. This method hides or shows the error message depending on the value of the result parameter it receives. When the user already exists, the error message is shown by setting the visibility to visible. When the user name is not already taken, the error message is hidden.

With this setup, the user will see an error message appaear as soon as she moves the focus away from the UserName text box.

Summary

By using ASP.NET AJAX, Page Methods and the Membership API, implementing a client side user name check is a matter of minutes. What's cool about this method is that it doesn't require a change to the existing sign up page. There's no need to rip apart the CreateUserWizard and add any HTML or CSS to existing elements. All you need to do is define a server side Page Method and write a bit of JavaScript.

Note that this is just a simple example of using Page Methods. It's easy to come up with many other useful examples that improve the user experience in your ASP.NET driven web site.

Download Files

Source Code for this Article


Where to Next?

Wonder where to go next? You can post a comment on this article.

Doc ID 494
Full URL https://imar.spaanjaars.com/494/checking-the-existence-of-an-aspnet-membership-username-with-aspnet-ajax
Short cut https://imar.spaanjaars.com/494/
Written by Imar Spaanjaars
Date Posted 06/28/2009 21:02
Listened to when writing Pioneer To the Falls by Interpol (Track 1 from the album: Our Love to Admire)

Comments

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the Doc ID of the document.

(Plain text only; no HTML or code that looks like HTML or XML. In other words, don't use < and >. Also no links allowed.