ArgumentNullException: Value cannot be null after setting up authentication with Identity
AE
1
Reputation point
I am getting this bizarre error without any kind of reference to a line in the code after setting up authentication using Identity. The strange thing is that everything was working fine until I deleted every record in my ApplicationUser table. What is the problem ?!
My Implementation of IUserStore and IPasswordStore
public class UserStore : IUserStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>
{
// IMPLEMENTING IUserStore
//////////////////////////////////
///
public async Task<IdentityResult> CreateAsync(ApplicationUser user, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
cancellationToken.ThrowIfCancellationRequested();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var addUserCommand = connection.CreateCommand();
addUserCommand.CommandText = @"
INSERT INTO ApplicationUser(userName, normalizedUserName, passwordHash)
VALUES (@userName, @normalizedUserName, @passwordHash)";
addUserCommand.Parameters.AddWithValue("@userName", user.UserName);
addUserCommand.Parameters.AddWithValue("@normalizedUserName", user.NormalizedUserName);
addUserCommand.Parameters.AddWithValue("@passwordHash", user.PasswordHash);
await addUserCommand.ExecuteNonQueryAsync();
var selectLastIdCommand = connection.CreateCommand();
string lastInsertedId = "";
selectLastIdCommand.CommandText = @"SELECT LAST_INSERT_ID();";
using var reader = await selectLastIdCommand.ExecuteReaderAsync();
while (reader.Read())
{
user.Id = Int32.Parse(reader[0].ToString());
}
reader.Close();
}
return IdentityResult.Success;
}
public async Task<IdentityResult> DeleteAsync(ApplicationUser user, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
cancellationToken.ThrowIfCancellationRequested();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var deleteUserCommand = connection.CreateCommand();
deleteUserCommand.CommandText = @"
DELETE FROM ApplicationUser
WHERE ApplicationUser.id = @id;";
deleteUserCommand.Parameters.AddWithValue("@id", user.Id);
deleteUserCommand.ExecuteNonQueryAsync();
}
return IdentityResult.Success;
}
public async Task<ApplicationUser> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
cancellationToken.ThrowIfCancellationRequested();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var findByIdCommand = connection.CreateCommand();
findByIdCommand.CommandText = @"
SELECT * FROM ApplicationUser
WHERE ApplicationUser.id = @id;";
findByIdCommand.Parameters.AddWithValue("@id", Int32.Parse(userId));
using var reader = await findByIdCommand.ExecuteReaderAsync();
ApplicationUser user = new ApplicationUser();
while (reader.Read())
{
user.Id = Int32.Parse(reader[0].ToString());
user.UserName = reader[1].ToString();
user.NormalizedUserName = reader[2].ToString();
user.PasswordHash = reader[3].ToString();
}
reader.Close();
return user;
}
}
public async Task<ApplicationUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
ApplicationUser user = new ApplicationUser();
cancellationToken.ThrowIfCancellationRequested();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var findByNameCommand = connection.CreateCommand();
findByNameCommand.CommandText = @"
SELECT * FROM ApplicationUser
WHERE normalizedUserName = @normalizedUserName;";
findByNameCommand.Parameters.AddWithValue("@normalizedUserName", normalizedUserName);
using var reader = await findByNameCommand.ExecuteReaderAsync();
while (reader.Read())
{
user.Id = Int32.Parse(reader[0].ToString());
user.UserName = reader[1].ToString();
user.NormalizedUserName = reader[2].ToString();
user.PasswordHash = reader[3].ToString();
}
reader.Close();
}
return user;
}
public Task<string> GetNormalizedUserNameAsync(ApplicationUser user, CancellationToken cancellationToken)
{
return Task.FromResult(user.NormalizedUserName);
}
public Task<string> GetUserIdAsync(ApplicationUser user, CancellationToken cancellationToken)
{
return Task.FromResult(user.Id.ToString());
}
public Task<string> GetUserNameAsync(ApplicationUser user, CancellationToken cancellationToken)
{
return Task.FromResult(user.UserName);
}
public Task SetNormalizedUserNameAsync(ApplicationUser user, string normalizedName, CancellationToken cancellationToken)
{
user.NormalizedUserName = normalizedName;
return Task.FromResult(0);
}
public Task SetUserNameAsync(ApplicationUser user, string userName, CancellationToken cancellationToken)
{
user.UserName = userName;
return Task.FromResult(0);
}
public async Task<IdentityResult> UpdateAsync(ApplicationUser user, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return IdentityResult.Success;
}
public void Dispose()
{
// Nothing to dispose.
}
// IMPLEMENTING IUserPasswordStore
//////////////////////////////////
///
public Task SetPasswordHashAsync(ApplicationUser user, string passwordHash, CancellationToken cancellationToken)
{
user.PasswordHash = passwordHash;
return Task.FromResult(0);
}
public Task<string> GetPasswordHashAsync(ApplicationUser user, CancellationToken cancellationToken)
{
return Task.FromResult(user.PasswordHash);
}
public Task<bool> HasPasswordAsync(ApplicationUser user, CancellationToken cancellationToken)
{
return Task.FromResult(user.PasswordHash != null);
}
}
My implementation of IRoleStore
public class RoleStore : IRoleStore<ApplicationRole>
{
public async Task<IdentityResult> CreateAsync(ApplicationRole role, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
cancellationToken.ThrowIfCancellationRequested();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var addRoleCommand = connection.CreateCommand();
addRoleCommand.CommandText = @"
INSERT INTO ApplicationRole(id,name,normalizedName)
VALUES(@id, @name, @normalizedName);";
addRoleCommand.Parameters.AddWithValue("@id", role.Id);
addRoleCommand.Parameters.AddWithValue("@name", role.Name);
addRoleCommand.Parameters.AddWithValue("@normalizedName", role.NormalizedName);
await addRoleCommand.ExecuteNonQueryAsync();
}
return IdentityResult.Success;
}
public async Task<IdentityResult> UpdateAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<IdentityResult> DeleteAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetRoleIdAsync(ApplicationRole role, CancellationToken cancellationToken)
{
return Task.FromResult(role.Id.ToString());
}
public Task<string> GetRoleNameAsync(ApplicationRole role, CancellationToken cancellationToken)
{
return Task.FromResult(role.Name);
}
public Task SetRoleNameAsync(ApplicationRole role, string roleName, CancellationToken cancellationToken)
{
role.Name = roleName;
return Task.FromResult(0);
}
public Task<string> GetNormalizedRoleNameAsync(ApplicationRole role, CancellationToken cancellationToken)
{
return Task.FromResult(role.NormalizedName);
}
public Task SetNormalizedRoleNameAsync(ApplicationRole role, string normalizedName, CancellationToken cancellationToken)
{
role.NormalizedName = normalizedName;
return Task.FromResult(0);
}
public async Task<ApplicationRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
cancellationToken.ThrowIfCancellationRequested();
ApplicationRole role = new ApplicationRole();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var findByIdCommand = connection.CreateCommand();
findByIdCommand.CommandText = @"
SELECT * FROM ApplicationUser
WHERE id = @id";
findByIdCommand.Parameters.AddWithValue("@id", roleId);
using var reader = await findByIdCommand.ExecuteReaderAsync();
while (reader.Read())
{
role.Id = Int32.Parse(reader[0].ToString());
role.Name = reader[1].ToString();
role.NormalizedName = reader[2].ToString();
}
reader.Close();
}
return role;
}
public async Task<ApplicationRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
var builder = new MySqlConnectionStringBuilder
{
//db connection info
};
cancellationToken.ThrowIfCancellationRequested();
ApplicationRole role = new ApplicationRole();
using (var connection = new MySqlConnection(builder.ConnectionString))
{
await connection.OpenAsync(cancellationToken);
var findByNameCommand = connection.CreateCommand();
findByNameCommand.CommandText = @"
SELECT * FROM ApplicationUser
WHERE normalizedName = @name";
findByNameCommand.Parameters.AddWithValue("@normalizedName", normalizedRoleName);
using var reader = await findByNameCommand.ExecuteReaderAsync();
while (reader.Read())
{
role.Id = Int32.Parse(reader[0].ToString());
role.Name = reader[1].ToString();
role.NormalizedName = reader[2].ToString();
}
reader.Close();
}
return role;
}
public void Dispose()
{
// Nothing to dispose.
}
}
ApplicationUser
public class ApplicationUser
{
public int Id { get; set; }
public string UserName { get; set; }
public string NormalizedUserName { get; set; }
public string PasswordHash { get; set; }
}
ApplicationRole
public class ApplicationRole
{
public int Id { get; set; }
public string Name { get; set; }
public string NormalizedName { get; set; }
}
Register RazorPage
This page would be the first thing the user requests.
public class RegisterModel : PageModel
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger _logger;
[BindProperty]
public AuthenticationInputModel model { get; set; }
public RegisterModel(UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
ILogger<RegisterModel> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
public void onGet()
{
model = new AuthenticationInputModel();
}
public async Task<IActionResult> OnPostRegister(AuthenticationInputModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.UserName };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToPage("/Index");
}
}
return Page();
}
}