How to Get List of User/Profile from Membership Provider? - asp.net

I am utilising this Membership Provider. I am stuck with getting the User List + Profile (FirstName, LastName, Title etc etc)
I know that there is a method for Membership.GetAllUsers() but I don't know how to combine this with FirstName, LastName that I stored in Profile Provider.
Thanks

Membership.GetAllUsers() returns a MembershipUserCollection, which you can use to access individual MembershipUser. Example:
MembershipUserCollection users = Membership.GetAllUsers();
string email = users["some_username"].Email;
You can also retrieve ProfileInfo in the similar way:
ProfileInfoCollection profiles = ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All);
DateTime lastActivity = profiles["some_username"].LastActivityDate;
However there are no FirstName and LastName properties by default, unless you manually specified them in your profile provider.
Check out MembershipUser class and ProfileInfo class for more details. You might also wanna check out SqlProfileProvider class as an example of profile provider, unless you already have implemented one.

First when you create a user, create a profile with the same username using:
// Create an empty Profile for the new User
ProfileCommon p = (ProfileCommon) ProfileCommon.Create("username", true);
Then to retrieve it next time..
// Retrieve a particular profile
ProfileCommon userProfile = Profile.GetProfile("username");
Thanks.

Related

How to get IdentityUser by Username

I have previously worked with Membership through "System.Web.Security.Membership"
Here, you can do the following:
var currentUser = Membership.GetUser();
var otherUser = Membership.GetUser(username);
...giving you a MembershipUser.
Now, with Identity, I can find a load of ways to get the current logged in user.
But no way to get another user.
I can use:
var userStore = new UserStore<IdentityUser>();
var userManager = new UserManager<IdentityUser>(userStore);
var user = userManager.Find(username, password);
But that takes both username and password, with no overload for just username.
How do i get the IdentityUser from only a username?
Almost every answer I find is connected to MVC.
This is for a WCF service, where authorization is made using Identity. And in some cases the user is getting to the site from an other site with a generated "token" - an encrypted string, containing the username. From here, user is logged in and a session-cookie is set, depending on users settings.
Also, is there a shorter way to get UserInformation?
"var currentUser = Membership.GetUser(username);"
is much more convenient than
"var user2 = (new UserManager((new UserStore()))).Find(username, password);"
UserManager has UserManager<TUser>.FindByNameAsync method. You can try using it to find user by name.

What is the right way to create ViewModels with Repository pattern

I am learning to use ASP.NET MVC with the Repository pattern.
I have a list of Users and a list of Roles. Users contain a RoleId, and Roles contain a RoleName and Id. I want to return a list of UsersWithRoles and put it in a ViewModel that has a UserName and a RoleName. What is the right way to proceed.
I am thinking of:
1) Get the list of Names and Roles and fill the ViewModel from the controller(foreach)
2) Join the Roles and Names in the Repository and return them as an Entity to the Controller, where I fill the ViewModel
3) Join the Roles and Names in the Repository and return as a ViewModel directly
u can done this by get user records using LINQ and using that user info u can again get record of role using LINQ. at the end u can add in custom model and that model u can send to respected view.
In Controller
Find Specific record and store common field (Primary Data) to the local variable
var Users = _Entity.UserInfoTable.Where(p => p.UserCode.Equals(UserID)).FirstOrDefault();
string strUserID = Users.UserID
strUserID hold the UserID
now using local variable get the role data specific to that user
var UserRole = _Entity.UserRoleTable.Where(p => p.UserCode.Equals(strUserID)).FirstOrDefault()
Final step : add UserRole data to the Custom/View model/Repo
CustomeModel cm = new CustomeModel();
cm.UserID = UserRole.UserID;
cm.RoleID = UserRole.RoleID;
cm.RoleName = UserRole.RoleName;
var usersWithRoles = (from u in Users
join r in Roles on r.Id equals u.RoleId
select new UserWithRoles{
UserName = u.UserName,
RoleName = r.RoleName
}).ToList();

Remove the domain name from User.Identity.Name

I have he following method inside my action method:-
repository.InsertOrUpdateRack(rj.Rack, User.Identity.Name, assetid);
But the user name generated from User.Identity.Name will prefix the username with the domain name as follow:-
DOMAINNAME\username
So is there a way to force the User.Identity.Name to retrieve the username only?
Thanks.
The domain forms part of the username so I don't think any of the methods/properties return what you need. Can you not just do:
var userName = User.Identity.Name.Split('\\')[1];
Not ideal but simple enough. If you want to keep it nicely hidden away you could create an extension method on IIdentity.
The VB equivalent is (where UserWindowsName could be a variable or control used to display the Windows User Name):
Dim userName As WindowsIdentity = HttpContext.Current.Request.LogonUserIdentity
UserWindowsName = userName.Name.Split("\"c)(1)
var name = Regex.Replace(HttpContext.User.Identity.Name, #"^.*\", "");

ASP.NET Membership: Where is Current User ID Stored?

Using ASP.NET membership, if I want to get information for the current user, I can call MembershipUser.GetUser()
So, somehow the system must know the ID of the current user.
If this is correct, and all I want is the ID of the current user, is there a way to get it without returning all the user information from the database?
I know I can get the username of the current user using User.Identity.Name, but I need the ID.
The short answer is no you can't get only userID without retrieve whole user info when you use built-in membership provider, only by this
MembershipUser user = Membership.GetUser();
string UserID = user.ProviderUserKey.ToString();
But if you want to have method or property which retrieve only userID, you must re-implement your own membership provider or(it's simply) to implement IPrincipal interface
To return the UserId, use the command bellow in your controller:
User.Identity.GetUserId();
To return the UserName, use:
User.Identity.Name;
To return the user:
var user = db.Users.Find(User.Identity.GetUserId());
Please refer to the post: How to get current user, and how to use User class in MVC5?
As you've guessed, the Membership API doesn't support what you want out of the box. In the past, I've used a helper class instead of creating my own provider. In this case it's pretty simple, maybe something like this:
public static object GetUserId() {
return GetUserId(HttpContext.Current.User.Identity.Name, true);
}
public static object GetUserId(string userName) {
return GetUserId(userName, true);
}
public static object GetUserId(string userName, bool UpdateLastActivity) {
using (SqlConnection c = new SqlConnection(CONNECTION_STRING)) {
string sql = #"
DECLARE #UserId uniqueidentifier
SELECT #UserId=u.UserId
FROM dbo.aspnet_Applications AS a
,dbo.aspnet_Users AS u
,dbo.aspnet_Membership AS m
WHERE
a.LoweredApplicationName=LOWER(#ApplicationName)
AND u.ApplicationId=a.ApplicationId
AND u.LoweredUserName=LOWER(#UserName)
AND u.UserId=m.UserId;
IF #UserId IS NOT NULL AND #UpdateLastActivity=1
UPDATE dbo.aspnet_Users
SET LastActivityDate=#CurrentTimeUtc
WHERE UserId=#UserId;
SELECT #UserId
";
using (SqlCommand cmd = new SqlCommand(sql, c)) {
cmd.Parameters.AddWithValue("#ApplicationName", Roles.ApplicationName);
cmd.Parameters.AddWithValue("#UserName", userName);
cmd.Parameters.AddWithValue("#UpdateLastActivity", UpdateLastActivity);
cmd.Parameters.AddWithValue("#CurrentTimeUtc", DateTime.UtcNow);
object id = null;
c.Open();
id = cmd.ExecuteScalar();
return id != DBNull.Value ? id : null;
}
}
}
Above is pretty similar to what's done in the Membership API when calling GetUser()
You can use MembershipUser.UserName to get the user id or try calling Membership.GetUser(User.Identity.Name) and see if that works for you.
After looking into this further, it seems that the ASP.NET Membership API does not track the user ID after all. It must track just the user name (User.Identity.Name). The ID is not required because Membership.GetUser() can find a user from an ID or user name.
In fact, Membership.GetUser() must simply translate to Membership.GetUser(User.Identity.Name). Since it can obtain the current user from the user name, there is no longer any reason to assume that the current user ID is cached anywhere.
So it appears the ID is not loaded into memory, and the only way to obtain the ID is to load the data from the database (which means loading the entire user record when using the ASP.NET Membership API).
Consider
int userId = WebSecurity.CurrentUserId;
Credit: https://stackoverflow.com/a/15382691/1268910

ASP.NET username change

I have an asp.net site which uses the ASP.net Membership provider. Each comment, entry etc in the DB is tracked by the userID.
Since MS doesn't provide a way to change the username, I've found the userNAME in the "users" table in the DB and there is only 1 place where the username appears.
My question is,
Is it safe to provide an "edit profile" page where the user is allowed to edit their own username. Of course i would handle this change in the background by directly changing the "username" value in the DB.
Are there any downsides to this ? I've created and modified some test accounts and it seems to be fine, i am just wondering if there is any known negatives to this before putting it into production.
cptScarlet's link was good, however I despise using stored procedures if I don't have to and I favor Entity Framework whenever possible. Here's what I did to change the user name, using EF 4.0 and .NET 4.0:
Right click project -> Add New Item -> ADO.NET Entity Data Model
Give it a proper name, I chose "MembershipModel.edmx" and click Add
Select Generate from database and click Next
Add the connection to your 'aspnetdb' database (the ASP.NET membership database)
Give it a proper name, I chose "MembershipEntities"
Click Next
Drill into Tables and select aspnet_Users
Change the Model Namespace to MembershipModel
Click Finish
Now you can add code to create the EF object context and modify the database:
public void ChangeUserName(string currentUserName, string newUserName)
{
using (var context = new MembershipEntities())
{
// Get the membership record from the database
var currentUserNameLowered = currentUserName.ToLower();
var membershipUser = context.aspnet_Users
.Where(u => u.LoweredUserName == currentUserNameLowered)
.FirstOrDefault();
if (membershipUser != null)
{
// Ensure that the new user name is not already being used
string newUserNameLowered = newUserName.ToLower();
if (!context.aspnet_Users.Any(u => u.LoweredUserName == newUserNameLowered))
{
membershipUser.UserName = newUserName;
membershipUser.LoweredUserName = newUserNameLowered;
context.SaveChanges();
}
}
}
}
Note: I did not account for application ID's in my code. I typically only ever have one application using the ASP.NET membership database, so if you have multiple apps, you'll need to account for that.

Resources