ASP.NET Core 2.2 - User's Last Login Date

This article will cover adding a create and last login date to a user with ASP.NET Core Identity. I will assume you have created a new ASP.NET Core 2.2 Razor Pages project with Individual User Accounts, updated the database with the CreateIdentitySchema migration, scaffolded the Identity UI and created an ApplicationUser extending the IdentityUser, see the Add UnconfirmedEmail Property to IdentityUser section in Require A Confirmed Email. Or you can download the free ASP.NET Core 2.2 - Bootstrap Native Project from Manage > Assets. I was able to restore, build and run the project with VS 2017, VS 2019 and VS Code.

Manage Assets.

There are plenty of discussions about DateTime vs DateTimeOffset. DateTimeOffset is a data type in C# and SQL (since MS SQL 2008). DateTimeOffset can include time zone information but I always use UTC for continuity. This article will demonstrate adding a required created date and a nullable last login date for a user.

Let's start by adding the DateTimeOffset properties to the ApplicationUser.

Edit Entities > ApplicationUser.cs, add properties:
public class ApplicationUser : IdentityUser
{
    [PersonalData]
    public string UnconfirmedEmail { get; set; }

    [PersonalData]
    public DateTimeOffset CreateDate { get; set; }

    [PersonalData]
    public DateTimeOffset LastLoginDate { get; set; }
}
Run the command "Add-Migration CreateAndLastLoginDates" from the Package Manager Console in VS 2017.
Edit the CreateAndLastLoginDates Migration class, declare LastLoginDate as nullable:
public partial class CreateAndLastLoginDates : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn(
            name: "CreateDate",
            table: "AspNetUsers",
            nullable: false,
            defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)));

        migrationBuilder.AddColumn(
            name: "LastLoginDate",
            table: "AspNetUsers",
            nullable: true);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "CreateDate",
            table: "AspNetUsers");

        migrationBuilder.DropColumn(
            name: "LastLoginDate",
            table: "AspNetUsers");
    }
}
Run the command "Update-Database".
Edit Register.cshtml.cs > OnPostAsync, add CreateDate to new user:
var user = new ApplicationUser { UserName = Input.UserName, Email = Input.Email, CreateDate = DateTimeOffset.UtcNow };
Edit Login.cshtml.cs > OnPostAsync > ModelState.IsValid > result.Succeeded, update LastLoginDate for user:
var user = await _userManager.FindByNameAsync(Input.UserName);
if (user == null)
{
    return NotFound("Unable to load user for update last login.");
}
user.LastLoginDate = DateTimeOffset.UtcNow;
var lastLoginResult = await _userManager.UpdateAsync(user);
if (!lastLoginResult.Succeeded)
{
    throw new InvalidOperationException($"Unexpected error occurred setting the last login date" +
        $" ({lastLoginResult.ToString()}) for user with ID '{user.Id}'.");
}
Edit ExternalLogin.cshtml.cs > OnGetCallbackAsync > ExternalLoginSignInAsync > result.Succeeded, update LastLoginDate for user:
var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
if (user == null)
{
    return NotFound("Unable to load user for update last login.");
}
user.LastLoginDate = DateTimeOffset.UtcNow;
var lastLoginResult = await _userManager.UpdateAsync(user);
if (!lastLoginResult.Succeeded)
{
    throw new InvalidOperationException($"Unexpected error occurred setting the last login date" +
        $" ({lastLoginResult.ToString()}) for user with ID '{user.Id}'.");
}

For LoginWith2fa and LoginWithRecoveryCode, you need to inject the ApplicationUserManager.

Edit LoginWith2fa.cshtml.cs > OnPostAsync > TwoFactorAuthenticatorSignInAsync > result.Succeeded, update LastLoginDate for user:
user.LastLoginDate = DateTimeOffset.UtcNow;
var lastLoginResult = await _userManager.UpdateAsync(user);
if (!lastLoginResult.Succeeded)
{
    throw new InvalidOperationException($"Unexpected error occurred setting the last login date" +
        $" ({lastLoginResult.ToString()}) for user with ID '{user.Id}'.");
}
Edit LoginWithRecoveryCode.cshtml.cs > OnPostAsync > TwoFactorRecoveryCodeSignInAsync > result.Succeeded, update LastLoginDate for user:
user.LastLoginDate = DateTimeOffset.UtcNow;
var lastLoginResult = await _userManager.UpdateAsync(user);
if (!lastLoginResult.Succeeded)
{
    throw new InvalidOperationException($"Unexpected error occurred setting the last login date" +
        $" ({lastLoginResult.ToString()}) for user with ID '{user.Id}'.");
}
Ken Haggerty
Created 04/14/19
Updated 04/14/19 19:24 GMT

Log In or Reset Quota to read more.

Article Tags:

Claims Identity Model Scaffold
Successfully completed. Thank you for contributing.
Contribute to enjoy content without advertisments.
Something went wrong. Please try again.

Comments(0)

Loading...
Loading...

Not accepting new comments.

Submit your comment. Comments are moderated.

User Image.
DisplayedName - Member Since ?