无法使用自定义属性更新AspNetUsers身份 [英] Not able to update AspNetUsers Identity with custom properties
问题描述
我想用自定义属性更新AspNetUsers表。我希望用户能够在注册后插入地址信息。有了代码,我没有任何错误,也没有更新表格。使用剃须刀页面创建模型和视图。
I want to update the AspNetUsers table with custom properties. I want the users to be able to insert address information after registering. With the code, I don't get any errors, and it doesn't update the table. The model and view are created with razor pages.
表格(当我尝试更新用户时为空,下面的信息为注册时添加地址信息的时间)
The table (the nulls are when I try to update the user, and the information below it is when adding address information when registering)
,当我让用户在注册时添加地址信息时,它会更新表格。注册剃刀页面是由Identity创建的,我将其放置在脚手架中,并向其中添加了自定义属性。
Although, when I let users add address information when registering, it does update the table.The register razor page is created by Identity, and I scaffolded the item and added my custom properties to it.
Address.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using bytme.Models;
using bytme.Data;
using Microsoft.EntityFrameworkCore;
namespace bytme.Areas.Identity.Pages.Account.Manage
{
public class AddressModel : PageModel
{
private readonly UserManager<UserModel> _userManager;
private readonly SignInManager<UserModel> _signInManager;
private readonly ILogger<AddressModel> _logger;
public AddressModel(
UserManager<UserModel> userManager,
SignInManager<UserModel> signInManager,
ILogger<AddressModel> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
[TempData]
public string StatusMessage { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Name")]
[StringLength(100, ErrorMessage = "Invalid input. Maximum is 100 characters.")]
public string name { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Surname")]
[StringLength(100, ErrorMessage = "Invalid input. Maximum is 100 characters.")]
public string surname { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Street")]
[StringLength(48, ErrorMessage = "The longest street name in the Netherlands is 48 characters.")]
public string street { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "House Number")]
[StringLength(5, ErrorMessage = "The longest house number in the Netherlands is 5 characters.")]
public string streetnumber { get; set; }
//[DataType(DataType.Text)]
//[Display(Name = "House Number Addition", Description = "For example A or II")]
//[StringLength(6, ErrorMessage = "
//public string streetnumberadd { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "City")]
[StringLength(28, ErrorMessage = "The longest place name in the Netherlands is 28 characters.")]
public string city { get; set; }
[Required]
[DataType(DataType.PostalCode)]
[Display(Name = "Postal Code")]
[RegularExpression(@"^[1-9][0-9]{3}\s?[a-zA-Z]{2}$", ErrorMessage = "Invalid zip, for example: 1234AB")]
public string zipcode { get; set; }
}
public void OnGet(string returnUrl = null)
{
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(InputModel model)
{
if (ModelState.IsValid)
{
// Get the current application user
var user = await _userManager.GetUserAsync(User);
//Update the details
user.name = model.name;
user.surname = model.surname;
user.street = model.street;
user.streetnumber = model.streetnumber;
user.city = model.city;
user.zipcode = model.zipcode;
// Update user address
var result = await _userManager.UpdateAsync(user);
}
_logger.LogInformation("User added their address information successfully.");
StatusMessage = "Your address information has been added.";
return RedirectToPage();
}
}
}
Address.cshtml
@page
@model AddressModel
@{
ViewData["Title"] = "Add Address Information";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@Html.Partial("_StatusMessage", Model.StatusMessage)
<div>
<h3>Change your account settings</h3>
<hr />
<div class="row">
<div class="col-md-3">
<partial name="_ManageNav" />
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-6">
<h4>@ViewData["Title"]</h4>
<form id="address-form" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.name"></label>
<input asp-for="Input.name" class="form-control" />
<span asp-validation-for="Input.name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.surname"></label>
<input asp-for="Input.surname" class="form-control" />
<span asp-validation-for="Input.surname" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.street"></label>
<input asp-for="Input.street" class="form-control" />
<span asp-validation-for="Input.street" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.streetnumber"></label>
<input asp-for="Input.streetnumber" class="form-control" />
<span asp-validation-for="Input.streetnumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.city"></label>
<input asp-for="Input.city" class="form-control" />
<span asp-validation-for="Input.city" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.zipcode"></label>
<input asp-for="Input.zipcode" class="form-control" />
<span asp-validation-for="Input.zipcode" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default" asp-page-handler="OnPostAsync">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Register.cshtml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Net.Mail;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using bytme.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace bytme.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class RegisterModel : PageModel
{
private readonly SignInManager<UserModel> _signInManager;
private readonly UserManager<UserModel> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<UserModel> userManager,
SignInManager<UserModel> 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
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Name")]
[StringLength(100, ErrorMessage = "Invalid input. Maximum is 100 characters.")]
public string name { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Surname")]
[StringLength(100, ErrorMessage = "Invalid input. Maximum is 100 characters.")]
public string surname { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Street")]
[StringLength(48, ErrorMessage = "The longest street name in the Netherlands is 48 characters.")]
public string street { get; set; }
[DataType(DataType.Text)]
[Display(Name = "House Number")]
[StringLength(5, ErrorMessage = "The longest house number in the Netherlands is 5 characters.")]
public string streetnumber { get; set; }
//[DataType(DataType.Text)]
//[Display(Name = "House Number Addition", Description = "For example A or II")]
//[StringLength(6, ErrorMessage = "
//public string streetnumberadd { get; set; }
[DataType(DataType.Text)]
[Display(Name = "City")]
[StringLength(28, ErrorMessage = "The longest place name in the Netherlands is 28 characters.")]
public string city { get; set; }
[DataType(DataType.PostalCode)]
[Display(Name = "Postal Code")]
[RegularExpression(@"^[1-9][0-9]{3}\s?[a-zA-Z]{2}$", ErrorMessage = "Invalid zip, for example: 1234AB")]
public string zipcode { get; set; }
}
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 UserModel
{
UserName = Input.Email,
Email = Input.Email,
name = Input.name,
surname = Input.surname,
street = Input.street,
streetnumber = Input.streetnumber,
city = Input.city,
zipcode = Input.zipcode
};
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
// confirmation code + custom URL creation
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
// mailmessage creation...
// ...
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();
}
}
}
Register.cshtml
@page
@model RegisterModel
@{
ViewData["Title"] = "Register";
}
<h2>@ViewData["Title"]</h2>
<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.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.name"></label>
<input asp-for="Input.name" class="form-control" />
<span asp-validation-for="Input.name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.surname"></label>
<input asp-for="Input.surname" class="form-control" />
<span asp-validation-for="Input.surname" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.street"></label>
<input asp-for="Input.street" class="form-control" />
<span asp-validation-for="Input.street" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.streetnumber"></label>
<input asp-for="Input.streetnumber" class="form-control" />
<span asp-validation-for="Input.streetnumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.city"></label>
<input asp-for="Input.city" class="form-control" />
<span asp-validation-for="Input.city" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.zipcode"></label>
<input asp-for="Input.zipcode" class="form-control" />
<span asp-validation-for="Input.zipcode" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Register</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
UserModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
namespace bytme.Models
{
public class UserModel : IdentityUser
{
public override string Id { get; set; }
public override string Email { get; set; }
public override string UserName { get; set; }
public override string PasswordHash { get; set; }
public string zipcode { get; set; }
public string city { get; set; }
public string street { get; set; }
public string streetnumber { get; set; }
public string name { get; set; }
public string surname { get; set; }
}
}
推荐答案
我重新创建了您的问题,并发现了以下问题。您的表显示空值的原因是事实,即方法中的参数 model
始终为空。
I recreated your problem and I found out the following. The reason why your table display null values is the fact, that the parameter model
in your method is always null.
公共异步任务< IActionResult> OnPostAsync(InputModel model)
因此,您正在通过 user
实体中的空值。绑定需要遵循一些约定。您在这里有两个选择:
So you are updating your properties over user
entity within null values. Binding needs to follow some convention. You have got two options here:
因为要绑定属性 Input
和 [BindProperty]
属性,其中视图在每种输入类型上使用标记 asp-for = Input.name,...
通过绑定属性直接访问。
Because you are binding your property Input
, with [BindProperty]
attribute where your view is using tag asp-for="Input.name", ...
over each input type, you might access directly via binded property.
//get rid of parameter model, access directly in method body
public async Task<IActionResult> OnPostAsync()
{
user = await _userManager.GetUserAsync(User);
user.name = Input.name;
user.surname = Input.surname;
user.street = Input.street;
user.streetnumber = Input.streetnumber;
user.city = Input.city;
user.zipcode = Input.zipcode;
var result = await _userManager.UpdateAsync(user);
return RedirectToPage();
}
或第二个选项-您可以在方法中使用参数,但必须遵循命名约定。如果您在视图中为每个输入
使用诸如 Input.name,Input.surname等
的名称,则该参数at方法也需要命名为 Input
。
or second option - you can use the parameter in your method, but it must follow the naming convention. If you use for each input
in your view naming like Input.name, Input.surname, etc.
, the parameter at method needs to be named as well Input
.
公共异步任务< IActionResult> OnPostAsync(InputModel input)
现在您可以通过参数访问绑定的值了(在参数的开头可以使用小写字母名称) 有关绑定的更多信息,请参见此链接
如果我已完成所有操作,请参见上文,我能够正确更新模型 (无空值)
If I've done everything, see above, I'm able to update the model correctly (without null values)
这篇关于无法使用自定义属性更新AspNetUsers身份的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!