Search code examples
c#asp.net-mvcasynchronousasync-awaitasp.net-identity-2

Identity 2.1, asynchronous programming, and updating additional user data


I understand what asynchronous programming is, but I have a hard time actually implementing it in my code. Identity 2.1 generates the CRUD methods and I want to add some code to it. How can I get the LINQ update to save? Do I need to use await? The AspNetUsers table updates fine, but not my UserProfiles table:

// POST: /Users/Edit/5    [Bind(Include = "FirstName,LastName,Email,Id,Address,City,State,PostalCode")]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(EditUserViewModel editUser, params string[] selectedRole)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindByIdAsync(editUser.Id);
            if (user == null)
            {
                return HttpNotFound();
            }

            user.UserName = editUser.Email;
            user.Email = editUser.Email;
            user.Address = editUser.Address;
            user.City = editUser.City;
            user.State = editUser.State;
            user.PostalCode = editUser.PostalCode;

            var userRoles = await UserManager.GetRolesAsync(user.Id);

            selectedRole = selectedRole ?? new string[] { };

            var result = await UserManager.AddToRolesAsync(user.Id, selectedRole.Except(userRoles).ToArray<string>());



            if (!result.Succeeded)
            {
                ModelState.AddModelError("", result.Errors.First());
                return View();
            }
            result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(selectedRole).ToArray<string>());

            if (!result.Succeeded)
            {
                ModelState.AddModelError("", result.Errors.First());
                return View();
            }
            //Update Firstname/Lastname
            var dbEntry = db.UserProfiles.Single(x => x.UserId == editUser.Id);
            dbEntry.FirstName = editUser.FirstName;
            dbEntry.LastName = editUser.LastName;
            db.SaveChanges();


            return RedirectToAction("Index");
        }
        ModelState.AddModelError("", "Something failed.");
        return View();
    }

Since my post was put on hold, let me explain my question in more detail. The var dbEntry is not updating on the db.SaveChanges(). When I step through the code, the editUser.FirstName and editUser.LastName does have a value.

var dbEntry does have a record to be updated. Again, db.SaveChanges() does not save.

I think what is happening is something with asynchronous programming. Since the method is public async Task Edit()

instead of:

public ActionResult Edit(). The update will work using public ActionResult Edit().

Since I'm not use to asynchronous programming (which I'm learning), how do I implement await in this method so var dbEntry will update?


Solution

  • The asynchronous aspect should not be a problem. The ApplicationDbContext of your UserManager is out-of-the-box configured with AutoDetectChangesEnabled == true. Chances are that your second DbContext is not. Turn it on if you like, or explicitly set db.Entry(dbEntry).State = EntityState.Modified before calling Save.