0

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?

JoshYates1980
  • 3,476
  • 2
  • 36
  • 57

2 Answers2

1

Well, it sort of sidesteps the question altogether, but why in the world are you using a separate entity to track profile data? One of the primary reasons Identity exists is to provide a more extensible user management system, meaning you don't have to try to tack on functionality like you used to have to with ASP.NET Membership.

public class ApplicationUser : IdentityUser
{
    // everything else already here

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

Then, just update it along with the user instance you're already updating:

user.UserName = editUser.Email;
user.Email = editUser.Email;
user.Address = editUser.Address;
user.City = editUser.City;
user.State = editUser.State;
user.PostalCode = editUser.PostalCode;
// add these
user.FirstName = editUser.FirstName;
user.LastName = editUser.LastName;

What's even more confusing is that ApplicationUser had already been extended in this way, because Address, City, State, and PostalCode are not on IdentityUser. Why you started handling first and last name information in a different way, then, is beyond me.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • It's not my call. I the inherited the database and the UserProfile table holds about 40 columns. – JoshYates1980 Mar 19 '15 at 16:33
  • You can refactor. The fact that you inherited bad code is no excuse to just keep using it. – Chris Pratt Mar 19 '15 at 16:35
  • I agree, but that doesn't answer the question why the update never executes. – JoshYates1980 Mar 19 '15 at 16:40
  • 2
    @ChrisPratt, some people work on a world that can't be changed by them. They have to adapt to that world. Maybe because there are a lot of applications already using that database. Maybe because it's a close product you are interacting with. ASP.NET Identity 2 is very good for doing what it does and lets everyone else out to dry. There's an excessive obsession on storing stuff and interoping was totally left out. – Paulo Morgado Mar 19 '15 at 17:06
1

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.

Oskar Lindberg
  • 2,255
  • 2
  • 16
  • 36