将 ASP.NET 核心身份用户属性保存在另一个表中

Posted

技术标签:

【中文标题】将 ASP.NET 核心身份用户属性保存在另一个表中【英文标题】:Save ASP.NET core Identity User attributes in another table 【发布时间】:2021-03-15 07:14:05 【问题描述】:

我正在开发一个 ASP .NET 核心 Web 应用程序。我使用 Identity UI 框架 在应用程序中进行用户注册和授权。我将身份用户继承到我的ApplicationUser 类,如下所示。它创建了一个名为ApplicationUser 的表,并成功保存了给定属性下的相关数据:(我使用的是Microsoft SQL 数据库)

ApplicationUser.cs

using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;

#nullable disable

namespace WebApp.Models

        public partial class ApplicationUser : IdentityUser<int>
        
            public ApplicationUser()
            
            

            public string FirstName  get; set; 
            public string MiddleName  get; set; 
            public string LastNam  get; set; 
            public DateTime? DateOfBirth  get; set; 
            public string Bio  get; set; 

            public virtual UserAddress UserAddress  get; set; 
        

然后我实现UserAddress模型类如下。它在数据库中创建另一个名为 "UserAddress"\

的表

UserAddress.cs

using System;
using System.Collections.Generic;

#nullable disable

namespace WebApp.Models

    public partial class UserAddress
    
        public int UserId  get; set; 
        public string BuildingNo  get; set; 
        public string Street  get; set; 
        public string City  get; set; 
        public string State  get; set; 
        public string ZipCode  get; set; 

        public virtual ApplicationUser User  get; set; 
    

接下来在 Identity UI 框架的 Areas 文件夹下,我将 Index.cshtml 文件更改如下。我插入新条目以输入用户的building number,该条目应保存在数据库中的UserAddress 表中。

Index.cshtml

@page
@model IndexModel
@
    ViewData["Title"] = "Profile";
    ViewData["ActivePage"] = ManageNavPages.Index;


<h4>@ViewData["Title"]</h4>
<partial name="_StatusMessage" model="Model.StatusMessage" />
<div class="row">
    <div class="col-md-12">
        <form id="profile-form" method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="=row d-flex flex-row">
                <div class="form-group col-md-6">
                    <label asp-for="Input.UserName"></label>
                    <input asp-for="Input.UserName" class="form-control" />
                </div>
            </div>
            <div class="=row d-flex flex-row">
                <div class="form-group col-md-6">
                    <label asp-for="Input.FirstName"></label>
                    <input asp-for="Input.FirstName" class="form-control" />
                </div>
                <div class="form-group col-md-6">
                    <label asp-for="Input.MiddleName"></label>
                    <input asp-for="Input.MiddleName" class="form-control" />
                </div>
            </div>
            <div class="=row d-flex flex-row">
                <div class="form-group col-md-6">
                    <label asp-for="Input.LastNam"></label>
                    <input asp-for="Input.LastNam" class="form-control" />
                </div>
            </div>
            <div class="=row d-flex flex-row">
                <div class="form-group col-md-6">
                    <label asp-for="Input.DateOfBirth"></label>
                    <input asp-for="Input.DateOfBirth" class="form-control" />
                </div>
                <div class="form-group col-md-6">
                    <label asp-for="Input.PhoneNumber"></label>
                    <input asp-for="Input.PhoneNumber" class="form-control" />
                    <span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
                </div>
             </div>
             <div class="=row d-flex flex-row">
                <div class="form-group col-md-6">
                        <label asp-for="Input.BuildingNo"></label>
                        <input asp-for="Input.BuildingNo" class="form-control" />
                </div>
             </div>
            <div class="=row d-flex flex-row">
                <div class="do-md-6">
                    <button id="update-profile-button" type="submit" class="btn btn-primary">Save</button>
                </div>
            </div>
         </form>
    </div>
</div>

@section Scripts 
    <partial name="_ValidationScriptsPartial" />

并且在Index.cshtml.cs文件中,我尝试将building number保存在UserAddress表中,如下所示,但无法将数据输入到表中。

Index.cshtml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using WebApp.Models;

namespace WebApp.Areas.Identity.Pages.Account.Manage

    public partial class IndexModel : PageModel
    
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;

        public IndexModel(
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager)
        
            _userManager = userManager;
            _signInManager = signInManager;
        

        public string BuildingNo  get; set; 
        public string Username  get; set; 

        [TempData]
        public string StatusMessage  get; set; 

        [BindProperty]
        public InputModel Input  get; set; 

        public class InputModel
        

            [DataType(DataType.Text)]
            [Display(Name = "User Name")]
            public string UserName  get; set; 

            [DataType(DataType.Text)]
            [Display(Name = "First name")]
            public string FirstName  get; set; 


            [DataType(DataType.Text)]
            [Display(Name = "Middle name")]
            public string MiddleName  get; set; 


            [DataType(DataType.Text)]
            [Display(Name = "Last name")]
            public string LastNam  get; set; 


            [Display(Name = "Date of Birth")]
            [DataType(DataType.Date)]
            public DateTime DateOfBirth  get; set; 

            [Phone]
            [Display(Name = "Phone number")]
            public string PhoneNumber  get; set; 

            [Display(Name = "Building No:")]
            [DataType(DataType.Text)]
            public string BuildingNo  get; set; 
        

        private async Task LoadAsync(ApplicationUser user)
        
            var userName = await _userManager.GetUserNameAsync(user);
            var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
            Username = userName;
            Input = new InputModel
            
                UserName = user.UserName,
                FirstName = user.FirstName,
                MiddleName = user.MiddleName,
                LastNam = user.LastNam,
                PhoneNumber = phoneNumber, 
            ;
            
        

        public async Task<IActionResult> OnGetAsync()
        
            var user = await _userManager.GetUserAsync(User);
            if (user == null)
            
                return NotFound($"Unable to load user with ID '_userManager.GetUserId(User)'.");
            

            await LoadAsync(user);
            return Page();
        

        public async Task<IActionResult> OnPostAsync()
        
            var user = await _userManager.GetUserAsync(User);
            if (user == null)
            
                return NotFound($"Unable to load user with ID '_userManager.GetUserId(User)'.");
            

            if (!ModelState.IsValid)
            
                await LoadAsync(user);
                return Page();
            

            var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
            if (Input.PhoneNumber != phoneNumber)
            
                var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
                if (!setPhoneResult.Succeeded)
                
                    StatusMessage = "Unexpected error when trying to set phone number.";
                    return RedirectToPage();
                
            
            if(Input.FirstName != user.FirstName)
            
                user.FirstName = Input.FirstName;
            

            if (Input.MiddleName != user.MiddleName)
            
                user.MiddleName = Input.MiddleName;
            
            if (Input.LastNam != user.LastNam)
            
                user.LastNam = Input.LastNam;
            
            if (Input.DateOfBirth != user.DateOfBirth)
            
                user.DateOfBirth = Input.DateOfBirth;
            
            if (Input.UserName != user.UserName)
            
                user.UserName = Input.UserName;
            
            
            user.UserAddress.BuildingNo = Input.BuildingNo; // I tried to enter the building address to the UserAddress table by using this code

            await _userManager.UpdateAsync(user);

            await _signInManager.RefreshSignInAsync(user);
            StatusMessage = "Your profile has been updated";
            return RedirectToPage();
        
    

请忽略上面我提供的冗长的Index.cshtml.cs 代码,我在我用来将输入building number 插入到 UserAddress 表的唯一代码附近进行了评论。即:user.UserAddress.BuildingNo = Input.BuildingNo;

这是条目视图的一部分: The entry view这是我在运行上述代码时遇到的错误: The error message

记录:ApplicationUser 表中的所有字段都已更新。但是当我尝试将数据插入UserAddress 表时会发生此错误。

我是漂亮的用户,对于一个非常了解 ASP.NET 核心身份用户的人来说,这是一个非常简单的问题。

如果有人可以帮我将输入 building number 保存在另一个名为 User Address 的表中,我请您帮忙?

提前致谢!!!

【问题讨论】:

能否请您检查您的user 对象,是否有UserAddress?如果它有 NULL,你不能赋值。你应该这样做```new UserAddress () BuildingNo = Input.BuildingNo; 【参考方案1】:

您可以像下面这样更改您的代码:

第一次使用代码获取当前user包括UserAddress

 var user = await _userManager.Users
                         .Include(x => x.UserAddress)
                         .SingleAsync(x => x.UserName== Input.UserName);

然后判断UserAddress是否存在并更新。

 if (user.UserAddress == null)
                
                    user.UserAddress = new Models.UserAddress
                    
                        BuildingNo = Input.BuildingNo
                    ;
                
                else
                
                    user.UserAddress.BuildingNo = Input.BuildingNo;
                

整个代码如下:

public async Task<IActionResult> OnPostAsync()
    
        //get the current user
        var user = await _userManager.Users
                         .Include(x => x.UserAddress)
                         .SingleAsync(x => x.UserName== Input.UserName);
        if (user == null)
        
            return NotFound($"Unable to load user with ID '_userManager.GetUserId(User)'.");
        

        if (!ModelState.IsValid)
        
            await LoadAsync(user);
            return Page();
        

        var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
        if (Input.PhoneNumber != phoneNumber)
        
            var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
            if (!setPhoneResult.Succeeded)
            
                StatusMessage = "Unexpected error when trying to set phone number.";
                return RedirectToPage();
            
        
        if(Input.FirstName != user.FirstName)
        
            user.FirstName = Input.FirstName;
        

        if (Input.MiddleName != user.MiddleName)
        
            user.MiddleName = Input.MiddleName;
        
        if (Input.LastNam != user.LastNam)
        
            user.LastNam = Input.LastNam;
        
        if (Input.DateOfBirth != user.DateOfBirth)
        
            user.DateOfBirth = Input.DateOfBirth;
        
        if (Input.UserName != user.UserName)
        
            user.UserName = Input.UserName;
        
        //insert the BuildingNo
        if (user.UserAddress == null)
                
                    user.UserAddress = new Models.UserAddress
                    
                        BuildingNo = Input.BuildingNo
                    ;
                
                else
                
                    user.UserAddress.BuildingNo = Input.BuildingNo;
                

        await _userManager.UpdateAsync(user);

        await _signInManager.RefreshSignInAsync(user);
        StatusMessage = "Your profile has been updated";
        return RedirectToPage();
    

【讨论】:

我会检查你的代码,让你知道它在工作的天气。非常感谢您的回答。

以上是关于将 ASP.NET 核心身份用户属性保存在另一个表中的主要内容,如果未能解决你的问题,请参考以下文章

Missed User 属性,用于计算 asp.net 核心身份中的用户/角色数

控制器 ASP.net 核心 2.1 中的 Jwt 角色身份验证

在 asp.net 核心中更新身份用户时并发失败

在 asp.net 核心中使用身份时未找到具有授权属性的操作

将 Forms 身份验证与 Windows 身份验证混合使用

在 asp.net 核心中使用返回 url