locked
Creating an Identity user outside of registration form results in NullReferenceException RRS feed

  • Question

  • User1148966005 posted

    I have a Hangfire job that tries to create Identity users based on an old database. Later on it would be run every day to update user list if required. Unfortunately it results in this error (coming from Hangfire):

    Failed to process the job '24': an exception occurred. Retry attempt 6 of 10 will be performed in 00:12:04.
    System.NullReferenceException: Object reference not set to an instance of an object.
    at userpanel.BatchRegistration.CreateUser(String providedEmail, String providedPassword, String providedTraccarId, Nullable\`1 providedIsAdmin) in C:\Users\Vostro2017\source\repos\userpanel\Jobs.cs:line 83
    at userpanel.Jobs.UpdateUsers() in C:\...\userpanel\Jobs.cs:line 40
    at userpanel.Jobs.UpdateUsers() in C:\...\userpanel\Jobs.cs:line 42
    at userpanel.Jobs.UpdateUsers() in C:\...\userpanel\Jobs.cs:line 42
    at userpanel.Jobs.UpdateUsers() in C:\...\userpanel\Jobs.cs:line 44
    at System.Runtime.CompilerServices.TaskAwaiter\`1.GetResult()

    I expected it to create users instead.

    Jobs.cs:

    namespace userpanel {
        public class Jobs {
            public static async Task<bool> UpdateUsers() {
                await using var conn = new NpgsqlConnection("Server=localhost;Port=5432;Database=Old;Username=postgres;Password=123456");
                await conn.OpenAsync();
    
                //
                // 1. Download old users and create Identity versions
                //
                await using (var cmd = new NpgsqlCommand("SELECT * FROM public.old_users ORDER BY id;", conn))
                await using (var reader = await cmd.ExecuteReaderAsync()) {
                    while (await reader.ReadAsync()) {
                        string providedOldId = reader.GetInt32(0).ToString();
                        string providedEmail = reader.GetString(2);
                        bool? providedIsAdmin = reader.GetBoolean(6);
                        string providedPassword = "123456";
                        await BatchRegistration.CreateUser(providedEmail, providedPassword, providedOldId, providedIsAdmin);
                    }
                }
                await conn.CloseAsync();
                return true;
            }
        }
    
        public class BatchRegistration : PageModel {
            public static SignInManager<ApplicationUser> _signInManager;
            public static UserManager<ApplicationUser> _userManager;
            public static ILogger<RegisterModel> _logger;
    
            public BatchRegistration(
                UserManager<ApplicationUser> userManager,
                SignInManager<ApplicationUser> signInManager,
                ILogger<RegisterModel> logger) {
                _userManager = userManager;
                _signInManager = signInManager;
                _logger = logger;
            }
    
            public static async Task CreateUser(string providedEmail, string providedPassword, string providedOldId, bool? providedIsAdmin) {
                bool IsAdmin = providedIsAdmin.HasValue != false;
                var user = new ApplicationUser {
                    UserName = providedEmail,
                    Email = providedEmail,
                    EmailConfirmed = true,
                    UserOldEmail = providedEmail,
                    UserOldId = providedOldId,
                    IsPaymentRequired = true,
                    IsAdministrator = IsAdmin,
                    Currency = 0.00
                    };
                foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(user)) {
                    string name = descriptor.Name;
                    object value = descriptor.GetValue(user);
                    Console.WriteLine("{0}={1}", name, value);
                }
                await _userManager.CreateAsync(user, providedPassword);
            }
        }
    }

    My model:

    public class ApplicationUser : IdentityUser {
        public string UserOldId { get; set; } // actually int, wouldn't let me migrate otherwise
        public string UserOldEmail { get; set; } 
        public bool IsPaymentRequired { get; set; }
        public bool IsAdministrator { get; set; }
        public double Currency { get; set; }
        public ICollection<UserDevice> Devices { get; } = new List<UserDevice>();
    }

    I couldn't find a way to create users like this, so I just copied registration form backend and modified it to my needs.

    I already tried filling my new ApplicationUser with IdentityUser data, but it didn't work. I also checked if any entry is empty/null - everything seems to be fine. I'm completely green to ASP.NET and I assume it's related to binding to UserManager somehow, since all data provided to _userManager.CreateAsync are valid.

    Maybe my approach is fundamentally wrong - I'm open for suggestions as well.

    Wednesday, January 8, 2020 10:17 AM

Answers

  • User1148966005 posted

    Problem solved. I realized I did so much wrong - I completely got rid of BatchRegistration - not sure why I made it in the first place. Then I moved everything to Jobs class and queued my job like this:

    BackgroundJob.Enqueue<Jobs>(j => j.UpdateUsers());

    Thanks to the guys at Stack Overflow.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 8, 2020 1:14 PM