ASP.Net 核心 2.2 Web 应用中的自定义标识



我正在按照演示从Asp Docs创建自定义IdentityUser。 我相信默认的身份用户只记录用户名、电子邮件和密码。 当我注册一个新帐户时,它实际上会被记录到 AspNetUser 表中。 但是,就我而言,我还想记录诸如名字,姓氏,DOB等内容...由于默认值不记录这些,我需要创建自定义身份用户。 按照 aspnet 文档实现自定义标识并更新视图的 html 后,我收到这个:

https://gyazo.com/5e1494dccc44d3cd03d24bf48816caf9(截图(

我不确定它从哪里接收"无效列名",我的 VisUser(自定义身份用户(中的列名与我的 sql 服务器 VisUser 表中的列名相匹配。

数据库上下文:

public class dbContext : IdentityDbContext<VisUser>
{
public dbContext(DbContextOptions<dbContext> options)
: base(options)
{
}
public DbSet<VisUser> VisUsers { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}

维斯用户

public class VisUser : IdentityUser
{
[Key]
public int UserId { get; set; }
[BindProperty]
[Required]
[MinLength(0), MaxLength(50), DataType(DataType.Text), Display(Name = "FirstName")]
public string FirstName { get; set; }
[BindProperty]
[Required]
[MinLength(0), MaxLength(2), DataType(DataType.Text), Display(Name = "Middle Initial")]
public string MiddleInitial { get; set; }
[BindProperty]
[Required]
[MinLength(1), MaxLength(50), DataType(DataType.Text), Display(Name = "Last Name")]
public string LastName { get; set; }
[BindProperty]
[Required]
[MinLength(4), MaxLength(50), DataType(DataType.Text), Display(Name = "Username")]
public string VisUserName { get; set; }
[BindProperty]
[Required]
[EmailAddress, MaxLength(256), Display(Name = "Email Address")]
public string VisEmail { get; set; }
[BindProperty]
[Required]
[MinLength(6), MaxLength(50), DataType(DataType.Password), Display(Name = "UserPassword")]
public string UserPassword { get; set; }
}

"注册页面"视图的 HTML

<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.FirstName"></label>
<input asp-for="Input.FirstName" class="form-control" />
<span asp-validation-for="Input.FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.MiddleInitial"></label>
<input asp-for="Input.MiddleInitial" class="form-control" />
<span asp-validation-for="Input.MiddleInitial" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.LastName"></label>
<input asp-for="Input.LastName" class="form-control" />
<span asp-validation-for="Input.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.VisEmail"></label>
<input asp-for="Input.VisEmail" class="form-control" />
<span asp-validation-for="Input.VisEmail" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.VisUserName"></label>
<input asp-for="Input.VisUserName" class="form-control" />
<span asp-validation-for="Input.VisUserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.UserPassword"></label>
<input asp-for="Input.UserPassword" class="form-control" />
<span asp-validation-for="Input.UserPassword" class="text-danger"></span>
</div>

<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

注册模型:

[AllowAnonymous]
public class RegisterModel : PageModel
{
private readonly SignInManager<VisUser> _signInManager;
private readonly UserManager<VisUser> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<VisUser> userManager,
SignInManager<VisUser> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}
[BindProperty]
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
public class InputModel : VisUser
{
}
public void OnGet(string returnUrl = null)
{
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var user = new VisUser { UserName = Input.VisUserName, Email = Input.VisEmail };
var result = await _userManager.CreateAsync(user, Input.UserPassword);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}

当我运行它时,我收到错误,指出我的列名找不到或不匹配。 我想发生的事情是将VisUser的信息存储在sql服务器中的VisUser表中,并将AspNetUser的相关信息也存储在那里,以便我可以与SigninManager,UserManager等一起使用操作。 希望你能帮忙,提前谢谢你!

该错误仅表示数据库与代码不同步。您需要在进行这些更改后生成并应用迁移,以便数据库将具有您添加的新 props 的支持列。

也就是说,您在这里还有其他一些问题应该解决。从IdentityUser继承时,不要定义密钥。IdentityUser已经有一个密钥属性。如果您希望该键是 int 而不是字符串的默认值,那么已经有一种方法可以做到这一点。

同样,删除UserPassword属性。您最终会将用户的密码(可能是纯文本(保存到数据库中,这当然是一个非常糟糕的主意。密码功能已内置于IdentityUser.

其中一些可能是为了满足InputModel的需求。但是,绝对不应以这种方式将实体用作模型。您需要一个特定于视图需求的类(即,将帖子绑定到的内容和显示的内容(,以及一个特定于数据库需求的类(即持久保存的内容(。不要将两者混为一谈,否则你只会有问题。

最后,不要对用户输入(如名字和姓氏、电子邮件等(施加任意限制,例如最大长度。真的没有意义。所有字符串道具都表示为NVARCHAR,因此它们只消耗它们需要消耗的空间。例如,如果名字的长度为 10 个字符,则无论您是否施加 50 个限制,它都将占用 20 个字节(unicode(。如果有一些东西实际上有一个逻辑定义的长度,比如社会安全号码、邮政编码等,那很好。否则,请将其保持打开状态。

最新更新