Problem with ChangePassword Control

Problem with ChangePassword Control

Old forum URL: forums.lhotka.net/forums/t/4481.aspx


cliffordru posted on Saturday, March 08, 2008

I am using a custom identity, principle and membership provider as outlines in Rocky's book.  I am having an issue with the ChangePassword control however.  When you click the control's update password button nothing seems to happen.  I am setting the MembershipProvider property on the control to my custom membership provider, but nothing in my provider gets called.

Does the control first call the Membership User class?  If so, how can I get the control to work with my custom Csla authentication?

Thanks!

skagen00 replied on Saturday, March 08, 2008

Rocky illustrates how you can begin to implement a custom membership provider in the book by handling ValidateUser (if I remember right), but one must understand that the Membership API (which the Login, ChangePassword, PasswordRecovery, CreateUserWizard interface with) is far larger than ValidateUser. The ASP.Net configuration tool, as well, uses the Membership API in conjunction with the Role API.

Your web application can use one or many Membership providers or Role providers, and there is the capability for a default one was well. The Membership API ends up calling the underlying default provider. You can also utilize any of the providers (non-default ones) directly. Which membership provider and role provider fulfill the behavior for the Membership API and Role API is definable in your Web.config file.

By default, the ChangePassword control, among others, will use the default provider. However, you can explicitly set the provider to one of the non-default ones too - there's a public property for MembershipProvider on the ChangePassword control, for example.

If you look at the code below (from the ChangePasswordControl) it calls LoginUtil.GetProvider(this.MembershipProvider). If it's null or empty, it uses the default Membership Provider and if it's not, it'll use the provider matching this.MembershipProvider.

As you can see, it then invokes provider.GetUser, and then uses the MembershipUser to change the password.

private void AttemptChangePassword()
{
    if ((this.Page == null) || this.Page.IsValid)
    {
        LoginCancelEventArgs e = new LoginCancelEventArgs();
        this.OnChangingPassword(e);
        if (!e.Cancel)
        {
            MembershipProvider provider = LoginUtil.GetProvider(this.MembershipProvider);
            MembershipUser user = provider.GetUser(this.UserNameInternal, false, false);
            string newPasswordInternal = this.NewPasswordInternal;
            if ((user != null) && user.ChangePassword(this.CurrentPasswordInternal, newPasswordInternal, false))
            {
                if (user.IsApproved && !user.IsLockedOut)
                {
                    FormsAuthentication.SetAuthCookie(this.UserNameInternal, false);
                }
                this.OnChangedPassword(EventArgs.Empty);
                this.PerformSuccessAction(user.Email, user.UserName, newPasswordInternal);
            }
            else
            {
                this.OnChangePasswordError(EventArgs.Empty);
                string changePasswordFailureText = this.ChangePasswordFailureText;
                if (!string.IsNullOrEmpty(changePasswordFailureText))
                {
                    changePasswordFailureText = string.Format(CultureInfo.CurrentCulture, changePasswordFailureText, new object[] { provider.MinRequiredPasswordLength, provider.MinRequiredNonAlphanumericCharacters });
                }
                this.SetFailureTextLabel(this._changePasswordContainer, changePasswordFailureText);
            }
        }
    }
}

The bottom line is that there is a lot of implementation to these Membership providers and Role providers.

I can think of four choices:

1) Use your custom provider as-is, and just write your own change password control, which really isn't a big deal.

2) Completely write out your custom provider to fully implement the Membership interface, which is way too much work.

3) Use the SqlMembershipProvider (and SqlRoleProvider if you like) as-is. The big downside is that they don't support an n-tier solution and the "dataportal" concept. Your authentication database would need to be on the Web server.

4) Pursue the approach outlined in this thread, which I can tell has been difficult for a few people to implement -- but I have been using this concept without issues for quite some time. This wraps the SqlMembershipProvider and SqlRoleProvider in what I call a CslaMembershipProvider and CslaRoleProvider - essentially you get all the bells and whistles of the provided implementation (in the .Net framework) along with dataportal support.

http://forums.lhotka.net/forums/thread/14844.aspx

Good luck,

Chris

 

cliffordru replied on Saturday, March 08, 2008

Thanks Chris.  Turns out it was code that I had added to the Application_AcquireRequestState event handler in the global.asax.  Basically this event handler was being called before the Membership Provider was called from the ChangePassword control and I had code in the event handler that was short circuiting the call to the provider and that is why it was never executing any of its methods.

skagen00 replied on Saturday, March 08, 2008

Oops! Glad you were able to figure it out easily.

Copyright (c) Marimer LLC