error when logging in with ASP.NET Core Identity in WPF application
Body: I am developing a WPF application using ASP.NET Core Identity for user authentication. The signup process works correctly, and I can see the user in my database after creating an account. However, when I try to log in with the correct username and password, I get the following error message in a popup:
An error occurred: Value cannot be null (Parameter 'provider')
Here is the relevant code for my App.xaml.cs
:
using CISN_app.Data;
using CISN_app.Models;
using CISN_app.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
namespace CISN_app
{
public partial class App : Application
{
private ServiceProvider _serviceProvider = null!;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var services = new ServiceCollection();
ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider();
var loginWindow = _serviceProvider.GetRequiredService<Login>();
loginWindow.Show();
}
private void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer("Data Source=my_server;Initial Catalog=my_database;Integrated Security=True;Connect Timeout=30;Encrypt=False;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False"));
services.AddLogging();
services.AddIdentity<User, IdentityRole>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 1;
options.SignIn.RequireConfirmedAccount = false;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
services.AddHttpContextAccessor();
services.AddTransient<Login>();
services.AddTransient<SignUp>();
services.AddScoped<SignInManager<User>, CustomSignInManager>();
}
}
}
And here is the custom SignInManager
implementation:
using CISN_app.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
namespace CISN_app.Services
{
public class CustomSignInManager : SignInManager<User>
{
public CustomSignInManager(UserManager<User> userManager,
IUserClaimsPrincipalFactory<User> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<User>> logger,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<User> confirmation)
: base(userManager, null, claimsFactory, optionsAccessor, logger, schemes, confirmation)
{
}
public override Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
return base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure);
}
}
}
Here is the LoginButton_Click
method:
private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
string username = UsernameTextBox.Text;
string password = PasswordBox.Password;
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
{
MessageBox.Show("Please enter both username and password.", "Login Error", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var context = new DefaultHttpContext();
_httpContextAccessor.HttpContext = context;
try
{
var result = await _signInManager.PasswordSignInAsync(username, password, false, false).ConfigureAwait(false);
if (!result.Succeeded)
{
MessageBox.Show("Invalid username or password.", "Login Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
Application.Current.Dispatcher.Invoke(() =>
{
Menu menuWindow = new Menu();
menuWindow.Show();
this.Close();
});
}
}
catch (ArgumentNullException ex)
{
MessageBox.Show($"An error occurred: {ex.Message}", "Login Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}