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

Save ASP.NET core Identity User attributes in another table

我正在开发一个 ASP .NET 核心 Web 应用程序。我在应用程序中使用 Identity UI 框架 进行用户注册和授权。我将 Identity User 继承给我的 ApplicationUser class,如下所示。它创建一个名为 ApplicationUser 的 table 并在给定属性下成功保存相关数据:(我正在使用 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模型class如下。它在名为 "UserAddress"\

的数据库中创建另一个 table

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 table 中。

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 文件中,我尝试将 UserAddress table 中的 building number 保存为如下,但无法将数据输入 table.

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 table 的代码附近进行了注释。即:
user.UserAddress.BuildingNo = Input.BuildingNo;

这是条目的视图部分: The entry view
这是我在上面的代码为 运行: The error message

时遇到的错误

备案: ApplicationUser table 中的所有字段已更新。但是当我尝试将数据插入 UserAddress table.

时会发生此错误

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

我恳请是否有人可以帮助我将输入 building number 保存在另一个名为 User Address?

的 table 中

提前致谢!!!

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

首先使用代码获取当前 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();
    }