|
Subject:
|
ManageUsers
|
|
Posted By:
|
GameGorilla
|
Post Date:
|
4/8/2008 4:27:07 PM
|
What is the benefit to the private collection in the ManageUsers page?
private MembershipUserCollection allUsers = Membership.GetAllUsers();
Correct me if I am wrong, but any postback will cause a whole new requerying of all the users, right? That seems pretty extreme to me.
Does the membership provider cache that data perhaps?
|
|
Reply By:
|
Lee Dumond
|
Reply Date:
|
4/8/2008 9:27:15 PM
|
Not really that extreme, if you're only talking 7 users. ;-)
In a real-life scenario, you might consider replacing this with the overload of GetAllUsers(int pageIndex, int pageSize, out int totalRecords) as to limit the number of users that are fetched when populating the grid, and then implement paging in the grid using the same method.
|
|
Reply By:
|
GameGorilla
|
Reply Date:
|
4/9/2008 3:05:03 PM
|
Well that would take care of the case when you were actually trying to show all users or at least a page of them. (It would mess up the TotalUsers count but I'm not really concerned about that.) It just seemed strange that the reason that the datagrid is initially un-populated is to speed up the rendering of the page, and yet anything we do on the page would require refetching allusers (or a subset of them). And then, if I only want to see users with name starting with "G" then that would cause a postback and a GetAllUsers for the private collection, and then a GetUsersByUserName for the users starting with "G".
I guess I am just surprised, since the rest of the book seems pretty well thought out.
|
|
Reply By:
|
Lee Dumond
|
Reply Date:
|
4/9/2008 5:30:43 PM
|
There is actually an alternate way to handle this; and that's to get rid of the private allUsers variable altogether, and call Membership.GetAllUsers() explicitly only as needed.
1. Delete the line that contains the allUsers declaration.
2. In Page_Load, do: lblTotalUsers.Text = Membership.GetAllUsers().Count.ToString();
This method will now only be called upon the first page load, and the value will be cached in ViewState for subsequent postbacks.
3. In the BindUsers method, get rid of the following: if (reloadAllUsers) allUsers = Membership.GetAllUsers();
And, while you're at it, you can get rid of the parameter in the signature and just have BindUsers(), while of course changing all references to match. The only time this method is ever passed "true" is in the RowDeleting method, and we're now instead going to call GetAllUsers() directly in that method.
4. In gvwUsers_RowDeleting, do this: lblTotalUsers.Text = Membership.GetAllUsers().Count.ToString();
With the code altered this way, the only time the database is queried (or requeried) for the list of all users is either upon initial page load, or after a delete operation, which is exactly what you want to happen.
Again, for large membership lists, I would combine the above strategy with the paging-enabled overload of GetAllUsers for even better performance.
|
|
Reply By:
|
Lee Dumond
|
Reply Date:
|
4/9/2008 8:45:59 PM
|
I should probably also point out that the delete logic is slightly flawed, in that it deletes the user and their profile, but does not delete the user from the UsersInRoles table, not does it delete the user from the PersonalizationPerUser table.
I would suggest the following for "fully" delete a user:
protected void gvwUsers_RowDeleting(object sender, GridViewDeleteEventArgs e) { string userName = gvwUsers.DataKeys[e.RowIndex].Value.ToString(); ProfileManager.DeleteProfile(userName); if (Roles.GetRolesForUser(userName).Length > 0) Roles.RemoveUserFromRoles(userName, Roles.GetRolesForUser(userName)); PersonalizationAdministration.ResetUserState("~/Default.aspx", userName); Membership.DeleteUser(userName); BindUsers(true); lblTotalUsers.Text = Membership.GetAllUsers().Count.ToString(); }
|
|
Reply By:
|
GameGorilla
|
Reply Date:
|
4/10/2008 10:27:42 AM
|
Hmmm... interesting. And Thanks! I would have never caught that.
I'm gonna have to take a look at PersonalizationAdministration.ResetUserState and see what that is all about.
|
|
Reply By:
|
Lee Dumond
|
Reply Date:
|
4/10/2008 12:31:57 PM
|
quote: Originally posted by GameGorilla
Hmmm... interesting. And Thanks! I would have never caught that.
I'm gonna have to take a look at PersonalizationAdministration.ResetUserState and see what that is all about.
You would actually want to call this for each page that has personalization (which in this site is only the home page).
|
|
Reply By:
|
GameGorilla
|
Reply Date:
|
4/10/2008 3:29:36 PM
|
Thanks.
I'm really not too happy with the whole membership system. About %50 of my site is businesses managing user accounts (customers and employees). It has been a huge hassle dealing with it all (extending the sqlmembership provider and using the sqltableprofile provider).
|
|
Reply By:
|
Lee Dumond
|
Reply Date:
|
4/10/2008 5:36:35 PM
|
quote: Originally posted by GameGorilla
Thanks.
I'm really not too happy with the whole membership system. About %50 of my site is businesses managing user accounts (customers and employees). It has been a huge hassle dealing with it all (extending the sqlmembership provider and using the sqltableprofile provider).
While the BeerHouse membership implementation is very basic, I think the architectural approach behind it is essentially pretty sound.
I've written about this before, but to me, TheBeerHouse should be treated as a guide -- a "demonstration of concept" if you will -- and not a "finished", ready-to-go site. The idea was to show off some of ASP.NET 2.0's new features, and to present an overall general approach of how to apply n-tier principles to an ASP.NET site; and in that I think it succeeds.
I see a lot of people trying to adopt the implementation hook-line-and-sinker as a fait accompli, which in my opinion is a mistake.
|
|
Reply By:
|
GameGorilla
|
Reply Date:
|
4/11/2008 10:17:20 AM
|
I was complaining more about Microsofts Memebership system in general, not the way TheBeerHouse used it (other than that pesky local variable that started this thread).
|
|
Reply By:
|
kalel_4444
|
Reply Date:
|
4/16/2008 4:17:17 AM
|
quote: Originally posted by Lee Dumond
I should probably also point out that the delete logic is slightly flawed, in that it deletes the user and their profile, but does not delete the user from the UsersInRoles table, not does it delete the user from the PersonalizationPerUser table.
I just discovered (what I'm assuming):
By adding Products/Items or participating in the poll anonymously inserts a UserId into the aspnet_User table, because the IsAnonymous field is "true".
Which bring me to this question. I've set in Web.config: <polls archiveIsPublic="true" votingLockByIP="false" votingLockByCookie="false" />
Does this mean because it's not locking by IP or Cookie, the alternative (or additionally) is to add an Anonymous User ? I think I'm a little lost on how caching works.
Lee, does your example above remove from all user associated tables, anonymous too ?
Thank you,
|