The LastLogin field in the AspNetUsers table is not getting updated even after a successful login

Sherpa 306 Reputation points
2024-03-06T22:16:08.55+00:00

I have implemented razor view based identity in asp.net core 6. The logging works fine. However, whenever someone logs in, I want the LastLogin field in the AspNetUsers table to be updated whenever a user logs in. However, it always stays at 0001-01-01 00:00:00.0000000. The following is the code by which the logging takes place in the Login.cshtml.cs page.

var result = await _signInManager.PasswordSignInAsync(user.Email, Input.Password, 
Input.RememberMe, lockoutOnFailure: true);

if (result.Succeeded)
{
    _logger.LogInformation("User logged in.");       
    return Redirect(URL);
}

I am new to asp.net core and identity. So, my apologies if it's a trivial question.

Developer technologies | ASP.NET | ASP.NET Core
{count} votes

Accepted answer
  1. Anonymous
    2024-03-07T03:38:22.72+00:00

    Hi @Sherpa,
    Shorten Answer:

    var result = await _signInManager.PasswordSignInAsync(user.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
    if (result.Succeeded)
    {
        _logger.LogInformation("User logged in.");
        var currentUser = await _userManager.FindByEmailAsync(user.Email);
        // Update the LastLogin property
        currentUser.LastLogin = DateTime.UtcNow;
        // Save changes to the database
        await _userManager.UpdateAsync(currentUser);
        return LocalRedirect(returnUrl);
    }
    

    Here is a whole working sample you could follow:
    Login.cshtml.cs

      public class LoginModel : PageModel
        {
            private readonly SignInManager<ApplicationUser> _signInManager;
            private readonly UserManager<ApplicationUser> _userManager;
            private readonly ILogger<LoginModel> _logger;
            public LoginModel(UserManager<ApplicationUser> userManager,SignInManager<ApplicationUser> signInManager, ILogger<LoginModel> logger)
            {
                _userManager = userManager;
                _signInManager = signInManager;
                _logger = logger;
            }
            /// <summary>
            ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
            ///     directly from your code. This API may change or be removed in future releases.
            /// </summary>
            [BindProperty]
            public InputModel Input { get; set; }
            /// <summary>
            ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
            ///     directly from your code. This API may change or be removed in future releases.
            /// </summary>
            public IList<AuthenticationScheme> ExternalLogins { get; set; }
            /// <summary>
            ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
            ///     directly from your code. This API may change or be removed in future releases.
            /// </summary>
            public string ReturnUrl { get; set; }
            /// <summary>
            ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
            ///     directly from your code. This API may change or be removed in future releases.
            /// </summary>
            [TempData]
            public string ErrorMessage { get; set; }
            /// <summary>
            ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
            ///     directly from your code. This API may change or be removed in future releases.
            /// </summary>
            public class InputModel
            {
                /// <summary>
                ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
                ///     directly from your code. This API may change or be removed in future releases.
                /// </summary>
                [Required]
                [EmailAddress]
                public string Email { get; set; }
                /// <summary>
                ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
                ///     directly from your code. This API may change or be removed in future releases.
                /// </summary>
                [Required]
                [DataType(DataType.Password)]
                public string Password { get; set; }
                /// <summary>
                ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
                ///     directly from your code. This API may change or be removed in future releases.
                /// </summary>
                [Display(Name = "Remember me?")]
                public bool RememberMe { get; set; }
            }
            public async Task OnGetAsync(string returnUrl = null)
            {
                if (!string.IsNullOrEmpty(ErrorMessage))
                {
                    ModelState.AddModelError(string.Empty, ErrorMessage);
                }
                returnUrl ??= Url.Content("~/");
                // Clear the existing external cookie to ensure a clean login process
                await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
                ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
                ReturnUrl = returnUrl;
            }
            public async Task<IActionResult> OnPostAsync(string returnUrl = null)
            {
                returnUrl ??= Url.Content("~/");
                ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
                if (ModelState.IsValid)
                {
                    // This doesn't count login failures towards account lockout
                    // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                    var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
                    if (result.Succeeded)
                    {
                        _logger.LogInformation("User logged in.");
                        var currentUser = await _userManager.FindByEmailAsync(Input.Email);
                        // Update the LastLogin property
                        currentUser.LastLogin = DateTime.UtcNow;
                        // Save changes to the database
                        await _userManager.UpdateAsync(currentUser);
                        return LocalRedirect(returnUrl);
                    }
                    if (result.RequiresTwoFactor)
                    {
                        return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
                    }
                    if (result.IsLockedOut)
                    {
                        _logger.LogWarning("User account locked out.");
                        return RedirectToPage("./Lockout");
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                        return Page();
                    }
                }
                // If we got this far, something failed, redisplay form
                return Page();
            }
        }
    

    ApplicationUser

    public class ApplicationUser:IdentityUser
    {
        public DateTime LastLogin { get; set; }
    }
    

    Besides, the default Identity framework would sign in after register the user. So be sure also add the update LastLogin code to Register.cshtml.cs.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
    Best regards,
    Rena

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.