Search code examples
c#asp.net.netcreateuserwizard

Cancel CreateUserWizard from CreatedUser Event


I am using a CreateUserWizard together with a custom MembershipProvider to add a user to our database. Currently the user is successfully added to the database and I am using the CreatedUser event to store the additional information captured on the form. This works fine; however, I want to be able to handle any error conditions during the update.

Is there a way to redisplay the CreateUserWizard form with an error should the update of the additional details fails?

Here is the code I have in the CreatedUser event:

protected void RegisterUserWizard_CreatedUser(object sender, EventArgs e)
{
    try
    {
        // Try to update the customer table with the additional information
        using (OrderEntities entities = new OrderEntities())
        {
            // Read in all the values from the form
            TextBox custTitle = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerTitle");
            TextBox custName = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerName");
            TextBox custSurname = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerSurname");
            TextBox custAddress1 = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerAddressLine1");
            TextBox custAddress2 = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerAddressLine2");
            TextBox custAddress3 = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerAddressLine3");
            TextBox custCity = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerCity");
            TextBox custCounty = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerCounty");
            TextBox custPostcode = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerPostcode");
            DropDownList custCountry = (DropDownList)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerCountry");

            Customer custInfo = entities.Customers.Where(c => c.UserName == RegisterUserWizard.UserName).FirstOrDefault();

            if (custInfo != null)
            {
                custInfo.Email = RegisterUserWizard.Email;
                custInfo.Password = RegisterUserWizard.Password;
                custInfo.Title = custTitle.Text;
                custInfo.Firstname = custName.Text;
                custInfo.Surname = custSurname.Text;
                custInfo.AddressLine1 = custAddress1.Text;
                custInfo.AddressLine2 = custAddress2.Text;
                custInfo.AddressLine3 = custAddress3.Text;
                custInfo.City = custCity.Text;
                custInfo.County = custCounty.Text;
                custInfo.Postcode = custPostcode.Text;
                custInfo.CountryID = custCountry.SelectedValue;
                custInfo.CreatedDate = DateTime.Now;

                entities.SaveChanges();

                FormsAuthentication.SetAuthCookie(RegisterUserWizard.UserName, false);

                // Redirect user back to calling page
                string continueUrl = RegisterUserWizard.ContinueDestinationPageUrl;
                if (String.IsNullOrEmpty(continueUrl))
                {
                    continueUrl = "~/";
                }
                Response.Redirect(continueUrl);

            }
            else
            {
                // Redisplay CreateUserWizard showing error message
            }
        }
    }
    catch
    {
        // Redisplay CreateUserWizard showing error message
    }
}

Many thanks in advance


Solution

  • OK, found a workaround-hack for this one

    First, the modified CreatedUser Event handler:

    protected void RegisterUserWizard_CreatedUser(object sender, EventArgs e)
    {
        try
        {
            // Try to update the customer table with the additional information
            using (OrderEntities entities = new OrderEntities())
            {
                // Read in all the values from the form
                TextBox custTitle = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerTitle");
                TextBox custName = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerName");
                TextBox custSurname = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerSurname");
                TextBox custAddress1 = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerAddressLine1");
                TextBox custAddress2 = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerAddressLine2");
                TextBox custAddress3 = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerAddressLine3");
                TextBox custCity = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerCity");
                TextBox custCounty = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerCounty");
                TextBox custPostcode = (TextBox)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerPostcode");
                DropDownList custCountry = (DropDownList)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomerCountry");
    
                Customer custInfo = entities.Customers.Where(c => c.UserName == RegisterUserWizard.UserName).FirstOrDefault();
    
                if (custInfo != null)
                {
                    custInfo.Email = RegisterUserWizard.Email;
                    custInfo.Password = RegisterUserWizard.Password;
                    custInfo.Title = custTitle.Text;
                    custInfo.Firstname = custName.Text;
                    custInfo.Surname = custSurname.Text;
                    custInfo.AddressLine1 = custAddress1.Text;
                    custInfo.AddressLine2 = custAddress2.Text;
                    custInfo.AddressLine3 = custAddress3.Text;
                    custInfo.City = custCity.Text;
                    custInfo.County = custCounty.Text;
                    custInfo.Postcode = custPostcode.Text;
                    custInfo.CountryID = custCountry.SelectedValue;
                    custInfo.CreatedDate = DateTime.Now;
    
                    entities.SaveChanges();
    
                    FormsAuthentication.SetAuthCookie(RegisterUserWizard.UserName, false);
    
                    // Redirect user back to calling page
                    string continueUrl = RegisterUserWizard.ContinueDestinationPageUrl;
                    if (String.IsNullOrEmpty(continueUrl))
                    {
                        continueUrl = "~/";
                    }
                    Response.Redirect(continueUrl);
    
                }
                else
                {
                    // Throw an Exception so that we redisplay CreateUserWizard showing error message
                    throw new Exception("An error occurred updating account details, please try again");
                }
            }
        }
        catch (Exception ex)
        {
            // Delete the incomplete user from the membership to avoid duplicate UserName errors if the user tries again
            Membership.DeleteUser(RegisterUserWizard.UserName); 
    
            // Store the error message in the Context and transfer back to the page preserving the form
            Context.Items.Add("ErrorMessage", ex.Message);
            Server.Transfer(Request.Url.PathAndQuery, true);
        }
    }
    

    Next, I added a CustomValidator to ContentTemplate so that I can display the error message:

    <asp:CustomValidator ID="CustomValidator" runat="server" ValidationGroup="RegisterUserValidationGroup" />
    

    Finally, I added a new handler for the CreatingUser event to read the error message from the Context and display it using the CustomValidator:

    void RegisterUserWizard_CreatingUser(object sender, LoginCancelEventArgs e)
    {
        // If we have received an error message in the Context then cancel the CreatingUser and display the message
        if (Context.Items["ErrorMessage"] != null)
        {
            CustomValidator custValidator = (CustomValidator)RegisterUserWizard.CreateUserStep.ContentTemplateContainer.FindControl("CustomValidator");
            custValidator.ErrorMessage = Context.Items["ErrorMessage"].ToString();
            custValidator.IsValid = false;
            e.Cancel = true;
        }
    }
    

    Now if an error occurs; I can display a friendly message, tidy up the MembershipUser and most importantly, the user doesn't end up re-typing all their details again before retrying.