Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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

share|improve this question
    
Have you checked to perform Update-Database, after changes to ApplicationUser? Also "Name" is a Class Reference, it shall be serialized or mapped appropriately in the OnModelCreating. –  jd4u Dec 8 '13 at 19:00
    
No there's no problem with that, the database structure is just the same as ApplicationUser. The fields of name is a column in the database (as Name_First, Name_Last and Name_NickName). My problem is with the file database not getting updated with the new values when I call UserManager.UpdateAsync(user). I just want to know how I'm supposed to go about updating the ApplicationUser (Users table) –  gldraphael Dec 9 '13 at 19:56
    
ApplicationUser and OnModelCreating code snippets can be useful to help solve this issue. From your comment, it seems to be mapping issue for the Name property and its parts. –  jd4u Dec 10 '13 at 8:47
    
@jd4u By updating the ApplicationUser (Users table) I meant the values in the table and not the structure of the table. Mappings are proper and are working with the register form. The info just can't be updated. –  gldraphael Dec 10 '13 at 12:55
add comment

7 Answers

up vote 7 down vote accepted

ok.. i had hours trying to figure why userManger.updateAsync will not persist the user data that we edit ... till i reach to the following conlcusion

confusion arise from the fact that we create the UserManger 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 savechanges to the dbcontext of the Identity.. so the question is how to get the Identity DBcontext in the easiest way !!??

and to solve this we should not create the UserManger 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);

you go to the context as follow:

var ctx = store.context;

then

ctx.saveChanges();

wahooooooo.. prsisted :)

hope this will help someone who pulled his hair for a few hours :P

share|improve this answer
    
shortcut to the last two step : store.context.saveChanges(); –  stackunderflow Mar 19 at 16:34
2  
finally .. for those who need full implementation this link is excellent weblogs.asp.net/imranbaloch/archive/2013/12/12/… –  stackunderflow Mar 19 at 17:28
add comment

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.

share|improve this answer
    
To the point, and +1 to simple security –  gldraphael Dec 15 '13 at 16:37
    
Yes `UpdateAsync just commits the update to the context, [...] save the context for it to commit to the database' –  subsci Feb 8 at 9:39
add comment

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.

share|improve this answer
add comment

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 project. 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();
 }

As always, thanks in advance for constructive criticism.

share|improve this answer
add comment

If you don't have every single field for ApplicationUser as well as IdentityUser the update will come back as successful but wont save the data in the database. If you have every last piece of data then it will save properly.

My solution is pretty simple:

ApplicationUser Model = UserManager.FindById(User.Identity.GetUserId())

Than simply 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;

Than call the async

IdentityResult result = await UserManager.UpdateAsync(Model);

I have thoroughly tested this and it works perfectly.

share|improve this answer
    
I've ended up with simular option. Just used Automapper for mapping model. It looks like this: Mapper.Map(AppUserViewModel, Model); –  Oleksii Aza Mar 21 at 15:29
    
meaning I can't let one of the fields remain null –  gldraphael Mar 29 at 17:52
add comment

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.

share|improve this answer
add comment

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()));

share|improve this answer
    
aren't the constraints checked while checking ModelState.IsValid ? –  gldraphael Dec 10 '13 at 13:35
    
ModelState checks for View Model. You are taking the ApplicationUser from Db using GetApplicationUser(). –  jd4u Dec 10 '13 at 13:37
    
Moreover, UpdateManager.Update is just performing one validation for username in default implementation before sending update call to UserStore. Try using UserStore directly for the debug purpose. –  jd4u Dec 10 '13 at 13:39
    
@anyone, While marking any answer not-useful, please read all and have a little context in mind. This answer is correct to the context. Moreover, the answer selected here is not a solution, its alternate approach ignoring the Identity Framework's core framework and directly working with database. –  jd4u Feb 9 at 6:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.