Aug 31 2006

Update email username with verification

Posted by admin under Membership profile and roles

When using email adresses as username and requiring verification by email as we have shown in earlier articles, there is one thing still we need to implement.

The user must be able to change their username (i.e email address) and we need to implement some verification scheme for that as well.

Part of my Edit profile page looks like this and not much to say, but instead lets dive directly into the code:


    protected void btnUpdate_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            MembershipUser mu = Membership.GetUser();
            //Update email
            System.Guid oGuid = new Guid( mu.ProviderUserKey.ToString() );
            //1. Write to temptable that an email is about to be changed
            DataSet ds = DataAccessSQL.DataAccess.User_InsertEmailChange(System.Configuration.ConfigurationManager.AppSettings["ConnString"],
                oGuid,
                UserName.Text);
            //2. Send email
            string sGuid = ds.Tables[0].Rows[0].ToString();
            string sHeader = "";
            string sBody = "";
            MailHelper.EmailChangeMail(sGuid, ref sHeader, ref sBody);
            MyContext.SendEmail(UserName.Text,
                sHeader, sBody, true);

            //3. Wait
        }
    }

The idea is this:

1. We have create an additional table (emailchange) in SQL Server:

2. When the user want to change the email address we insert an record into the table, using stored procedure User_InsertEmailChange


CREATE proc User_InsertEmailChange(@user_guid uniqueidentifier,
@emailtochangeto varchar(255) )
as
DECLARE @newid uniqueidentifier
SELECT  @newid = NEWID()
insert emailchange select @newid,getdate(), @emailtochangeto, 'N', @user_guid 
select @newid


GO

It inserts the userguid (from the provider) , the new emailaddress (they want to change to) and also generates a new guid - which is returned down to our GUI - string sGuid = ds.Tables[0].Rows[0].ToString();

We generate a new email to be sent (to the new address) which will contain a link with something like

http://www.aspcode.net/blabla/emailchange.aspx?id=sGuid

So, when the user receives the email (on the new email address) they click on the link and comes to emailchange.aspx - and NOW we are supposed to do the username/email swap:


string sKey = Request["id"].ToString();

System.Guid oGuid = new Guid(UserName.Text);
        //Update username
DataSet ds = DataAccessSQL.DataAccess.Change_Email(System.Configuration.ConfigurationManager.AppSettings["ConnString"],
            oGuid);

string sUserGuid = ds.Tables[0].Rows[0][0].ToString();
string sChanged = ds.Tables[0].Rows[0][1].ToString();
string sNewEmail = ds.Tables[0].Rows[0][2].ToString();
if (sChanged == "0")
    return;

//Change email...
MembershipUser memUser = Membership.GetUser(sNewEmail);
memUser.Email = sNewEmail;
Membership.UpdateUser(memUser);


//Log them in
System.Web.Security.FormsAuthentication.RedirectFromLoginPage(memUser.UserName,
   true);


Changing username is not directly supported in the provider model, but by using an stored procedure Change_Email, we can modify the tables directly.



CREATE proc Change_Email(@guid_id uniqueidentifier)
as
declare  @user_guid uniqueidentifier
declare  @emailchangeto varchar(255)
declare  @changed varchar(255)
select @user_guid=user_guid, @emailchangeto=emailtochangeto, @changed=changed from emailchange where id=@guid_id
UPDATE aspnet_Users SET UserName =@emailchangeto,
LoweredUserName = LOWER(@emailchangeto)
where userid=@user_guid and @changed='0'
select @user_guid, @changed, @emailchangeto


We simply retrieves all stuff from the emailchange table by using the id GUID and update aspnet_Users directly after that.

Last we change the email property in the profile:


        MembershipUser memUser = Membership.GetUser(sNewEmail);
        memUser.Email = sNewEmail;
        Membership.UpdateUser(memUser);