I'm trying to implements a multitenancy application following step by step the Scott Brady post here:
https://www.scottbrady91.com/ASPNET-Identity/Quick-and-Easy-ASPNET-Identity-Multitenancy
I'm not really sure where I should put these code lines:
var context = new ApplicationUserDbContext<ApplicationUser>("DefaultConnection");
var userStore = new ApplicationUserStore<ApplicationUser>(context) { TenantId = 1 };
var userManager = new UserManager<ApplicationUser, string>(userStore);
I have tried to use this into my login action in AccountController:
var context = new ApplicationDbContext();
var userStore = new ApplicationUserStore<ApplicationUser>(context) { TenantId = tenantId };
UserManager = new ApplicationUserManager(userStore);
SignInManager.UserManager = UserManager;
ApplicationUser userApp =await UserManager.FindByEmailAsync(model.Email);
But UserManager.FindByEmailAsync always returns null, any idea of what I should do to get this working? My real objetive is to SingIn User but always return Failure. And I think the problem is finding the ApplicationUser.
If you need additional information please, let me know, thanks in advance.
Your are Using the Classes directly. Give a try with this way...and make sure that you have the user with that gmail that you are providing.
var context = new ApplicationDbContext();
var store = new UserStore<ApplicationUser>(context);
var manager = new ApplicationUserManager(store);
ApplicationUser userApp=await manager.FindByEmailAsync(model.Email);
I am working on an asp.net application where I have huge database. I want to implement elastic search. Here is what I have done in code:
var node = new Uri("http://localhost:9200/");
var setting = new ConnectionSettings(node);
setting.DefaultIndex("businessuser");
client = new ElasticClient(setting);
CanadaBusinessDBEntities db = new CanadaBusinessDBEntities();
client.DeleteIndex("businessuser", null);
var ListofBusiness = db.CanadaTables.ToList();
foreach (var Business in ListofBusiness)
{
var resutl = client.Index(Business, null);
}
This code is written in constructor which gets all records and then index them using elastic search. indexing is taking long time. I want to ask if this is correct way? I am new to elastic search. please suggest better way to do this.
Thanks.
You have to use ElasticsearchContext Class of Nest.
private readonly ElasticsearchContext _elasticsearchContext;
private const string ConnectionString = "http://localhost:9200";
private readonly IElasticsearchMappingResolver _elasticsearchMappingResolver;
_elasticsearchMappingResolver = new ElasticsearchMappingResolver();
_elasticsearchContext = new ElasticsearchContext(ConnectionString, new ElasticsearchSerializerConfiguration(_elasticsearchMappingResolver,true,true));
for Delete purpose you can use like that below
public void DeleteSkill(int Id)
{
_elasticsearchContext.DeleteDocument<Tag>(Id);
_elasticsearchContext.SaveChanges();
}
MVC 5 with asp.net identity 2.0
I understand how to get the currently logged in user id. I have a need to get the user id of a different user in the system. How is this done?
Ex. I need to get the user id of user names "fsmith" ...
Inside the AccountController you can call the following method to get user object and then get the User Id.
var user = await UserManager.FindByNameAsync(userName);
var userId = user.Id;
If you are not inside AccountController you can get the UserManager reference using the following code
var UserManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
To add to Shashi's useful answer...
If you're inside the account controller you can use the existing UserManager:
var user = await UserManager.FindByNameAsync(userName);
var userId = user.Id;
In other controllers (and maybe select other places where HttpContext is available) you create a User Manager with:
var um = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
But what it took me a while to realize is you can get at it just about anywhere with this last bit. For instance I used it in my seed method (in Configuration.cs) so I could seed the User property of another model:
var um = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(*insert-your-db-context-here*));
One way would to use the FindByNameAsync method of your user manager (or the generic version of it). It takes the name of the user (in your case "fsmith") and returns a task of a user object. This user object contains all the information available about that user.
A code snippet could look similar to the following one (if you're looking for the database ID):
var user = await UserManager.FindByNameAsync("fsmith");
var userId = user.Id;
EDIT
The UserManager instance is normally declared as follows (keep in mind that there are many ways of declaring it, for example when using Dependency Injection):
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
public UserManager<ApplicationUser> UserManager { get; private set; }
If you are using Bearing Token Auth, the above sample do not return an Application User.
Instead, use this:
ClaimsPrincipal currentUser = this.User;
var currentUserName = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
ApplicationUser user = await _userManager.FindByNameAsync(currentUserName);
return user.Id;
This works in apsnetcore 2.0. Have not tried in earlier versions.
I've added a couple of custom fields to my ApplicationUser:
public class ApplicationUser : IdentityUser
{
public enum BUserType {IndividualBuyer, IndividualSeller, Broker, Admin};
public string DisplayName;
public BUserType UserType;
I've updated all the views and controllers and I can create new users through my web app. Great.
However, my database seed function doesn't add the new fields to my users. For example, if I create a new user in my initializer, the new fields aren't filled in.
public class ListingInitializer : System.Data.Entity.DropCreateDatabaseAlways<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
if (!(context.Users.Any(u => u.UserName == "arnold#pizzashop.com")))
{
var userToInsert = new ApplicationUser { UserName = "arnold#pizzashop.com", DisplayName = "Arnold Toughguy", UserType = ApplicationUser.BUserType.IndividualSeller };
userManager.Create(userToInsert, "password1234");
}
So my question is, what could be wrong here? I assume userManager.Create does some fancy reflection-to-linq voodoo to find all the fields to persist. Is this not the case? Do I have to add bindings somewhere?
Just a thought, can you just try once after moving the enum definition outside of your POCO class, though I am not absolutely sure that the same will solve your problem.
You can also refer to this video, which may help you somewhat: http://thedatafarm.com/data-access/video-entity-framework-5-enums-and-moving-solution-from-ef-4-3/.
I've added custom fields to the ApplicationUser class
I've also created a form through which the user can enter/edit the fields.
However for some reason I'm not able to update the fields in the database.
[HttpPost]
[ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Manage(EditProfileViewModel model)
{
if (ModelState.IsValid)
{
// Get the current application user
var user = User.Identity.GetApplicationUser();
// Update the details
user.Name = new Name { First = model.FirstName, Last = model.LastName, Nickname = model.NickName };
user.Birthday = model.Birthdate;
// This is the part that doesn't work
var result = await UserManager.UpdateAsync(user);
// However, it always succeeds inspite of not updating the database
if (!result.Succeeded)
{
AddErrors(result);
}
}
return RedirectToAction("Manage");
}
My problem is similar to MVC5 ApplicationUser custom properties, but that seems to use an older version of Identity because the IdentityManager class doesn't seem to exist.
Can someone guide me on how to update User info in the database?
UPDATE:
If I include all the fields in the register form, all the values are stored in the appropriate field in a new record of the Users table from the database.
I don't know to make changes to the fields of an existing user (row in the users table). UserManager.UpdateAsync(user) doesn't work.
Also note my issue is more Identity oriented than EntityFramework
OK... I spent hours trying to figure why userManager.updateAsync would not persist the user data that we edit ... until I reached the following conclusion:
The confusion arises from the fact that we create the UserManager in one line like this:
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));
...then we use manager.UpdateAsync( user ); but that will update the user in the context, and then we will need to save changes to the dbcontext of the Identity. So, the question is how to get the Identity DBcontext in the easiest way.
To solve this, we should not create the UserManager in one line ... and here is how I do it:
var store = new UserStore<ApplicationUser>(new MyDbContext());
var manager = new UserManager(store);
then after updating the user by calling
manager.UpdateAsync(user);
then you go to the context
var ctx = store.context;
then
ctx.saveChanges();
wahooooooo...persisted :)
Hope this will help someone who pulled their hair for a few hours :P
If you leave any of the fields for ApplicationUser OR IdentityUser null the update will come back as successful but wont save the data in the database.
Example solution:
ApplicationUser model = UserManager.FindById(User.Identity.GetUserId())
Add the newly updated fields:
model.Email = AppUserViewModel.Email;
model.FName = AppUserViewModel.FName;
model.LName = AppUserViewModel.LName;
model.DOB = AppUserViewModel.DOB;
model.Gender = AppUserViewModel.Gender;
Call UpdateAsync
IdentityResult result = await UserManager.UpdateAsync(model);
I have tested this and it works.
The OWIN context allows you to get the db context. Seems to be working fine so far me, and after all, I got the idea from the ApplciationUserManager class which does the same thing.
internal void UpdateEmail(HttpContext context, string userName, string email)
{
var manager = context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindByName(userName);
user.Email = email;
user.EmailConfirmed = false;
manager.Update(user);
context.GetOwinContext().Get<ApplicationDbContext>().SaveChanges();
}
The UserManager did not work, and As #Kevin Junghans wrote,
UpdateAsync just commits the update to the context, you still need to save the context for it to commit to the database
Here is quick solution (prior to new features in ASP.net identity v2) I used in a web forms projetc. The
class AspNetUser :IdentityUser
Was migrated from SqlServerMembership aspnet_Users. And the context is defined:
public partial class MyContext : IdentityDbContext<AspNetUser>
I apologize for the reflection and synchronous code--if you put this in an async method, use await for the async calls and remove the Tasks and Wait()s. The arg, props, contains the names of properties to update.
public static void UpdateAspNetUser(AspNetUser user, string[] props)
{
MyContext context = new MyContext();
UserStore<AspNetUser> store = new UserStore<AspNetUser>(context);
Task<AspNetUser> cUser = store.FindByIdAsync(user.Id);
cUser.Wait();
AspNetUser oldUser = cUser.Result;
foreach (var prop in props)
{
PropertyInfo pi = typeof(AspNetUser).GetProperty(prop);
var val = pi.GetValue(user);
pi.SetValue(oldUser, val);
}
Task task = store.UpdateAsync(oldUser);
task.Wait();
context.SaveChanges();
}
I also had problems using UpdateAsync when developing a version of SimpleSecurity that uses ASP.NET Identity. For example, I added a feature to do a password reset that needed to add a password reset token to the user information. At first I tried using UpdateAsync and it got the same results as you did. I ended up wrapping the user entity in a repository pattern and got it to work. You can look at the SimpleSecurity project for an example. After working with ASP.NET Identity more (documentation is still non-existent) I think that UpdateAsync just commits the update to the context, you still need to save the context for it to commit to the database.
I have tried the functionality in the same way and when i call UserManager.Updateasync method it succeeds but there is no update in the database. After spending some time i found another solution to update the data in aspnetusers table which is following:
1) you need to create UserDbContext class inheriting from IdentityDbContext class like this:
public class UserDbContext:IdentityDbContext<UserInfo>
{
public UserDbContext():
base("DefaultConnection")
{
this.Configuration.ProxyCreationEnabled = false;
}
}
2) then in Account controller update user information like this:
UserDbContext userDbContext = new UserDbContext();
userDbContext.Entry(user).State = System.Data.Entity.EntityState.Modified;
await userDbContext.SaveChangesAsync();
where user is your updated entity.
hope this will help you.
Excellent!!!
IdentityResult result = await UserManager.UpdateAsync(user);
Based on your question and also noted in comment.
Can someone guide me on how to update User info in the database?
Yes, the code is correct for updating any ApplicationUser to the database.
IdentityResult result = await UserManager.UpdateAsync(user);
Check for constrains of all field's required values
Check for UserManager is created using ApplicationUser.
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
This works for me. I'm using Identity 2.0, it looks like GetApplicationUser isn't there anymore.
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (!string.IsNullOrEmpty(form["FirstName"]))
{
user.FirstName = form["FirstName"];
}
if (!string.IsNullOrEmpty(form["LastName"]))
{
user.LastName = form["LastName"];
}
IdentityResult result = await UserManager.UpdateAsync(user);
I am using the new EF & Identity Core and I have the same issue, with the addition that I've got this error:
The instance of entity type cannot be tracked because another instance
of this type with the same key is already being tracked.
With the new DI model I added the constructor's Controller the context to the DB.
I tried to see what are the conflict with _conext.ChangeTracker.Entries() and adding AsNoTracking() to my calls without success.
I only need to change the state of my object (in this case Identity)
_context.Entry(user).State = EntityState.Modified;
var result = await _userManager.UpdateAsync(user);
And worked without create another store or object and mapping.
I hope someone else is useful my two cents.
Add the following code to your Startup.Auth.cs file under the static constructor:
UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
The UserManagerFactory setting line of code is what you use to associate your custom DataContext with the UserManager. Once you have done that, then you can get an instance of the UserManager in your ApiController and the UserManager.UpdateAsync(user) method will work because it is using your DataContext to save the extra properties you've added to your custom application user.
I am using .Net Core 3.1 or higher version.Please follow the solution:
public class UpdateAssignUserRole
{
public string username { get; set; }
public string rolename { get; set; }
public bool IsEdit { get; set; }
}
private async Task UpdateSeedUsers(UserManager<IdentityUser> userManager, UpdateAssignUserRole updateassignUsername)
{
IList<Users> Users = await FindByUserName(updateassignUsername.username);
if (await userManager.FindByNameAsync(updateassignUsername.username) != null)
{
var user = new IdentityUser
{
UserName = updateassignUsername.username,
Email = Users[0].Email,
};
var result = await userManager.FindByNameAsync(updateassignUsername.username);
if (result != null)
{
IdentityResult deletionResult = await userManager.RemoveFromRolesAsync(result, await userManager.GetRolesAsync(result));
if (deletionResult != null)
{
await userManager.AddToRoleAsync(result, updateassignUsername.rolename);
}
}
}
}