问题
I'm trying to add a user programmatically to ASP.NET MVC Identity.
The error I'm encountering is: UserManager threw an exception of type 'System.NullReferenceException'
This function is called through a POST not originating from this site. It sits right below public async Task<ActionResult> Register(RegisterViewModel model)
in the AccountController.
[AllowAnonymous]
public async Task<bool> GenerateUser(string email)
{
var user = new ApplicationUser { UserName = email, Email = email };
string password = System.Web.Security.Membership.GeneratePassword(12, 4);
var result = await UserManager.CreateAsync(user, password);
if (result.Succeeded)
{
// Omitted
}
else { AddErrors(result); }
return true;
}
I have also attempted to use the below code to perform the same action, but I get the error that special characters can't be in the UserName (I am using an email address), but this is definitely allowed as it's how all my users are created using public async Task<ActionResult> Register(RegisterViewModel model)
.
string password = System.Web.Security.Membership.GeneratePassword(12, 4);
var store = new Microsoft.AspNet.Identity.EntityFramework.UserStore<ApplicationUser>();
var manager = new ApplicationUserManager(store);
var user = new ApplicationUser() { Email = email, UserName = email };
var result = manager.Create(user, password);
The user object is the same as if I had filled a form to create a new user on the site (using public async Task<ActionResult> Register(RegisterViewModel model)
), and the password is just a string, also the same.
public async Task<ActionResult> Register(RegisterViewModel model)
is as per the scaffolded default but here it is below anyway for reference:
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
//await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
//return RedirectToAction("Index", "Home");
// TODO: Email Sent
return View("ConfirmationSent");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
Edit:
I call the function with:
var result = new AccountController().GenerateUser(model.emailAddress);
Edit2:
As asked for: This is the class definition for the ApplicationUserManager
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 8,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
回答1:
The issue is with the UserManager, this solves the issue.
ApplicationDbContext context = new ApplicationDbContext();
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
UserManager.UserValidator = new UserValidator<ApplicationUser>(UserManager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
string password = System.Web.Security.Membership.GeneratePassword(12, 4);
var user = new ApplicationUser();
user.Email = model.Email;
user.UserName = model.Email;
string userPWD = password;
var result = UserManager.Create(user, userPWD);
来源:https://stackoverflow.com/questions/54667962/create-user-programmatically-using-c-sharp-asp-net-mvc-identity