How To Let Users Change Their Email Address in TheBeerHouse Starter Kit
If you’ve ever worked with the The BeerHouse Starter Kit featured in the Wrox book ASP.NET 2.0 Website Programming: Problem – Design - Solution, you may have noticed that the author neglected to provide a mechanism to allow users to change their email address after signing up. Here is a brief tutorial that shows how to add that functionality.
As a Wrox author, I like to prowl the Wrox P2P Forums from time to time. It’s interesting to note that the forum for the above mentioned book is still quite active, even though last month marked the 3rd year of the book’s release. The BeerHouse Starter Kit application is still downloaded quite frequently, and from what I understand the book is still a brisk seller too. I’ve been a big fan of this remarkable book for years, and was proud to write a companion to it last year that shows how to implement Linq to SQL for data access in the application.
The Problem
Occasionally a reader will contact me with a BeerHouse question. One of the most common is this one from Haroud that hit my inbox last week:
I just downloaded the app… I configured and installed it without any hint of strain. I figured email is not part of the profile provider. How can I get users to be able to update / change their email in the EditProfile.aspx page?
Well, Haroud is absolutely right. In ASP.NET, the Profile system is a great place to store all kinds of user personal and contact information – name, address, telephone number, and so on. A user’s email address, however, is generally maintained by the Membership provider, not the Profile provider.
The EditProfile.aspx page allows an authenticated user to change his or her profile information (it employs a user control for this) and password (through an ASP.NET ChangePassword server control), but there’s no way provided to let the user change his email address.
The Solution
The first thing you need to do is to add some controls to the UI to allow the user to input the change. Open EditProfile.aspx, go to the source code markup, and right under where the password-change area ends, add the following markup. (I’ve included some of the lines that come before and after to help you find where to place this code.)
...
asp:ChangePassword>
<p>
p>
<%
1: --Begin added lines--
%>
<hr style="width: 100%; height: 1px;" noshade="noshade" />
<div class="sectiontitle">
Change your email addressdiv>
<p>
p>
<table cellpadding="2">
<tr>
<td style="width: 110px;" class="fieldname">
<asp:Label runat="server" ID="lblEmail" AssociatedControlID="txtEmail"
Text="Email address:" />
td>
<td style="width: 300px;">
<asp:TextBox ID="txtEmail" runat="server" Width="100%" />
td>
<td>
<asp:RequiredFieldValidator ID="valRequireEmail" runat="server"
ControlToValidate="txtEmail" SetFocusOnError="true" Display="Dynamic"
ErrorMessage="Email address is required." ToolTip="Email address is required."
ValidationGroup="ChangeEmail" Text="*" />
<asp:RegularExpressionValidator runat="server" ID="valEmailPattern"
Display="Dynamic" SetFocusOnError="true" ValidationGroup="ChangeEmail"
ControlToValidate="txtEmail" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
ErrorMessage="The e-mail address you specified is not well-formed." Text="*" />
td>
tr>
<tr>
<td colspan="2" align="right">
<asp:Label runat="server" ID="lblEmailChangeSuccess" SkinID="FeedbackOK"
EnableViewState="false" />
<asp:Label ID="lblEmailChangeFail" runat="server" SkinID="FeedbackKO"
EnableViewState="false" />
<asp:Button ID="btnEmail" runat="server" Text="Change Email"
ValidationGroup="ChangeEmail" OnClick="btnEmail_Click" />
td>
tr>
table>
<asp:ValidationSummary runat="server" ID="valEmailSummary" ValidationGroup="ChangeEmail"
ShowMessageBox="true" ShowSummary="false" />
<%
1: --End added lines--
%>
<hr style="width: 100%; height: 1px;" noshade="noshade" />
<div class="sectiontitle">
Change your profilediv>
<p>
p>
...
Because the TBH_MembershipProvider is defined in web.config with the attribute requiresUniqueEmail="true", failing to provide any input (that is, trying to save an empty email address) will throw an ArgumentException. Here, we provide a RequiredFieldValidator to prevent that from happening. Note that there is also a RegularExpressionValidator to ensure that the email address is well-formed. This validator uses the same regular expression that Register.aspx (the signup page) does.
Your page should now look like the following:
The page looks good, but of course the email-changing functionality doesn’t work yet. We have to add some code to the page for that.
The first thing to add is a Page_Load method that lets the text box be populated with the user’s current email address. This method uses the Membership.GetUser method to obtain a reference to the current user.
protected void Page_Load(object sender, EventArgs e)
{
//add theses lines
if (!IsPostBack)
{
MembershipUser user = Membership.GetUser();
if (user != null)
{
txtEmail.Text = user.Email;
}
}
}
Then, we need to add the method that fires when the Change Email button is clicked.
//add this method
protected void btnEmail_Click(object sender, EventArgs e)
{
if (IsValid)
{
MembershipUser user = Membership.GetUser();
if (user != null && txtEmail.Text != user.Email)
{
user.Email = txtEmail.Text;
try
{
Membership.UpdateUser(user);
lblEmailChangeSuccess.Text = "Your email address was successfully changed.";
}
catch (ProviderException)
{
lblEmailChangeFail.Text = "A user with that email address already exists. Your address was not changed.";
}
}
}
}
Note the second if statement. If for some reason the GetUser method fails to retrieve the current member from the database, nothing will happen. Also, if the user attempts to “change” his email address to the one he already has (which, of course, is no change at all), again nothing happens.
Once we get past that second conditional, the user’s email address is changed to the new email address. After doing that, the UpdateUser method is called to save the change. If that works, a message appears in the page that indicates the change was successful.
Behind the scenes, the Membership.UpdateUser method uses the SqlMembershipProvider.UpdateUser method to persist membership information to the database. The SqlMembershipProvider will throw an exception if the email address is null or empty – but because we’ve used a RequiredFieldValidator, we’ve eliminated that possibility. However, the SqlMembershipProvider will also throw an exception if the email is equal to an existing email address in the database when requiresUniqueEmail="true". We need to use exception handling to determine if that is the case, and inform the user accordingly.
Summary
In this blog post, you learned how to add controls to the EditProfile.aspx page that let a user input changes to his or her email address.
You learned how to use the GetUser method to retrieve a reference to the current user, and how to retrieve the user’s email address. You also learned how to use the UpdateUser method to save a new email address to the database, and how to handle the case where the new email address is already being used by another member.
The BeerHouse starter kit application and accompanying book can teach you a lot about building ASP.NET web sites. Have fun with it, and don’t hesitate to post your questions to the Wrox P2P Forum, where there are lots of professional ASP.NET programmers ready and willing to help you.
Subscribe to this blog for more cool content like this!
You've been kicked (a good thing) - Trackback from DotNetKicks.com