views:

262

answers:

1

Hi everybody,

I'm currently working on a membership system for my web application, which is based on forms authentication from the framework.

I created some users with the integrated tool, and the login is perfectly working. But now what I want to do is to give administrator the capability to create, modify, delete users.

So here is what I've got right now:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim muc As MembershipUserCollection = Membership.GetAllUsers()

    ComboBox1.DataSource = muc
    ComboBox1.DataValueField = "UserName"
    ComboBox1.DataTextField = "UserName"
    ComboBox1.DataBind()
End Sub

Protected Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ComboBox1.SelectedIndexChanged

    Dim userName As String = ComboBox1.SelectedValue

    Dim mu As MembershipUser = Membership.GetUser(userName)

    Dim userRoles As String() = Roles.GetRolesForUser(userName)

    tbComments.Text = mu.Comment
    tbEmail.Text = mu.Email
    lblUserName.Text = mu.UserName
End Sub

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    Dim userName As String = ComboBox1.SelectedValue
    Dim mu As MembershipUser = Membership.GetUser(userName)

    If Not mu Is Nothing Then
        Try
            mu.Comment = tbComments.Text
            Membership.UpdateUser(mu)

            mu.Email = tbEmail.Text
            Membership.UpdateUser(mu)

            mu.IsApproved = True
            Membership.UpdateUser(mu)

            mu = Nothing
        Catch ex As Exception
            Console.WriteLine(ex.ToString())
        End Try
    End If

    DetailPanel.Visible = False
End Sub

The problem is that the record doesn't seem to be updated in the database. I made the multiple calls to Membership.UpdateUser after reading this blog entry, but it didn't change anything.

A strange thing I noticed while debugging, is that when I enter the Button1_Click method, Membership.GetUser(userName) returns me values from my precedent attempt ! I don't really understand what I'm missing.

Does someone have a clue ?

Thanks in advance !

+3  A: 

First:

The blog entry you cite is just wrong.

Here is the method you are calling, tell me if you see an indication that it needs to be called multiple times to update multiple properties:

public override void UpdateUser(MembershipUser user)
{
    if (user == null)
    {
        throw new ArgumentNullException("user");
    }
    SecUtility.CheckParameter(ref user.UserName, true, true, true, 0x100, "UserName");
    string email = user.Email;
    SecUtility.CheckParameter(ref email, this.RequiresUniqueEmail, this.RequiresUniqueEmail, false, 0x100, "Email");
    user.Email = email;
    try
    {
        SqlConnectionHolder connection = null;
        try
        {
            connection = SqlConnectionHelper.GetConnection(this._sqlConnectionString, true);
            this.CheckSchemaVersion(connection.Connection);
            SqlCommand command = new SqlCommand("dbo.aspnet_Membership_UpdateUser", connection.Connection);
            command.CommandTimeout = this.CommandTimeout;
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(this.CreateInputParam("@ApplicationName", SqlDbType.NVarChar, this.ApplicationName));
            command.Parameters.Add(this.CreateInputParam("@UserName", SqlDbType.NVarChar, user.UserName));
            command.Parameters.Add(this.CreateInputParam("@Email", SqlDbType.NVarChar, user.Email));
            command.Parameters.Add(this.CreateInputParam("@Comment", SqlDbType.NText, user.Comment));
            command.Parameters.Add(this.CreateInputParam("@IsApproved", SqlDbType.Bit, user.IsApproved ? 1 : 0));
            command.Parameters.Add(this.CreateInputParam("@LastLoginDate", SqlDbType.DateTime, user.LastLoginDate.ToUniversalTime()));
            command.Parameters.Add(this.CreateInputParam("@LastActivityDate", SqlDbType.DateTime, user.LastActivityDate.ToUniversalTime()));
            command.Parameters.Add(this.CreateInputParam("@UniqueEmail", SqlDbType.Int, this.RequiresUniqueEmail ? 1 : 0));
            command.Parameters.Add(this.CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));
            SqlParameter parameter = new SqlParameter("@ReturnValue", SqlDbType.Int);
            parameter.Direction = ParameterDirection.ReturnValue;
            command.Parameters.Add(parameter);
            command.ExecuteNonQuery();
            int status = (parameter.Value != null) ? ((int) parameter.Value) : -1;
            if (status != 0)
            {
                throw new ProviderException(this.GetExceptionText(status));
            }
        }
        finally
        {
            if (connection != null)
            {
                connection.Close();
                connection = null;
            }
        }
    }
    catch
    {
        throw;
    }
}

Second:

You are rebinding your list every postback. This needs to be done only once and the list is stored in viewstate.

Here is a working implementation:

UpdateUser.aspx

<%@ Page Language="vb" %>

<script runat="server">

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        ' be sure that DropDownList1.AutoPostBack = true

        If Not IsPostBack Then
            BindUserList()
        End If
    End Sub


    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ComboBox1.SelectedIndexChanged
        DisplayDetails(ComboBox1.SelectedValue)
    End Sub


    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
        Dim approved As Boolean = True
        Dim username As String = ComboBox1.SelectedValue
        Dim comments As String = tbComments.Text
        Dim email As String = tbEmail.Text

        UpdateUser(username, approved, comments, email)
    End Sub

    Private Sub BindUserList()
        '' you only need to databind once, the datasource is stored in viewstate
        Dim muc As MembershipUserCollection = Membership.GetAllUsers()

        ComboBox1.DataSource = muc
        ComboBox1.DataValueField = "UserName"
        ComboBox1.DataTextField = "UserName"
        ComboBox1.DataBind()
        '' initialize the selection
        ComboBox1_SelectedIndexChanged(ComboBox1, EventArgs.Empty)
    End Sub


    Private Sub DisplayDetails(ByVal userName As String)
        Dim mu As MembershipUser = Membership.GetUser(userName)

        Dim userRoles As String() = Roles.GetRolesForUser(userName)

        tbComments.Text = mu.Comment
        tbEmail.Text = mu.Email
        lblUserName.Text = mu.UserName
    End Sub

    Private Sub UpdateUser(ByVal userName As String, ByVal approved As Boolean, ByVal comments As String, ByVal email As String)
        Dim mu As MembershipUser = Membership.GetUser(userName)
        If Not mu Is Nothing Then
            Try

                mu.Comment = comments
                mu.Email = email
                mu.IsApproved = approved

                Membership.UpdateUser(mu)

                ErrLabel.Text = ""
            Catch ex As Exception
                ErrLabel.Text = ex.Message
            End Try
        End If
    End Sub
</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="ComboBox1" runat="server" AutoPostBack="True">
        </asp:DropDownList>
    </div>
    <p>
        UserName:<asp:Label ID="lblUserName" runat="server" Text=""></asp:Label><br />
        Email:<asp:TextBox ID="tbEmail" runat="server"></asp:TextBox><br />
        Comments:<asp:TextBox ID="tbComments" runat="server"></asp:TextBox><br />
    </p>
    <asp:Button ID="Button1" runat="server" Text="Update" Height="26px" Width="61px" /><br />
    <asp:Label ID="ErrLabel" runat="server" Text=""></asp:Label>
    </form>
</body>
</html>
Sky Sanders