Обновление AspNetUsers с дополнительными свойствами не будет работать - PullRequest
0 голосов
/ 19 октября 2018

Goodevening.Я застрял на чем-то, что не могу исправить себя.Я создал страницу бритвы с именами Address.cshtml.cs (модель) и Address.cshtml (просмотр) в моем проекте, чтобы пользователи могли добавлять свои пользовательские данные ПОСЛЕ регистрации.И var result = await _userManager.UpdateAsync(user); не похоже на это.Я попробовал два способа обновить его в базе данных:

Первая попытка

  [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> AccountChange(UserModel 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);
            }


            //await _signInManager.RefreshSignInAsync(User);
            _logger.LogInformation("User added their address information successfully.");
            StatusMessage = "Your address information has been added.";

            return RedirectToPage();

        }
    }

Вторая попытка

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(UserModel model)
{
    if (ModelState.IsValid)
    {
        UserModel u = await _userManager.FindByIdAsync(model.Id);
        u.name = model.name;
        u.surname = model.surname;
        u.street = model.street;
        u.streetnumber = model.streetnumber;
        u.city = model.city;
        u.zipcode = model.zipcode;
        await _userManager.UpdateAsync(u);
        return RedirectToAction("Index");
    }
    return RedirectToPage();
}

Как я могу это исправить? Я добавил весь необходимый код ниже.

Address.cshtml.cs

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;
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> AccountChange(UserModel 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);
            }


            //await _signInManager.RefreshSignInAsync(User);
            _logger.LogInformation("User added their address information successfully.");
            StatusMessage = "Your address information has been added.";

            return RedirectToPage();

        }
    }
}

Address.cshtml

@page
@model AddressModel
@inject SignInManager<UserModel> SignInManager
@using Microsoft.AspNetCore.Identity
@using bytme.Models;
@{
    ViewData["Title"] = "Add Address Information";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@Html.Partial("_StatusMessage", Model.StatusMessage)
@{
    var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any();
}
<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="change-password-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">Submit</button>
                    </form>
                </div>
            </div>

        </div>
    </div>
</div>

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

UserModel.cs

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; }
    }
}

ApplicationDbContext.cs

namespace bytme.Data
{
    public class ApplicationDbContext : IdentityDbContext<UserModel>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
        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 DbSet<bytme.Models.Item> Items { get; set; }
        public DbSet<bytme.Models.ItemCategories> ItemCategories { get; set; }
        public DbSet<bytme.Models.UserModel> UserModels { get; set; }
        public DbSet<bytme.Models.OrderHistory> OrderHistories { get; set; }
        public DbSet<bytme.Models.OrderMain> OrderMains { get; set; }
        public DbSet<bytme.Models.OrderStatus> OrderStatuses { get; set; }
        public DbSet<bytme.Models.WishlistModel> WishlistModels { get; set; }
        public DbSet<bytme.Models.ShoppingCartModel> ShoppingCartModels { get; set; }
    }
}

1 Ответ

0 голосов
/ 20 октября 2018

После проверки кода я обнаружил несколько проблем.

1. У меня есть сомнения по поводу вашего метода записи AccountChange.Следующие соглашения должны соблюдаться.Согласно документам Microsoft о бритвенных страницах, генерируется несколько обработчиков методов по умолчанию, например: OnGet OnPost OnGetAsync OnPostAsync и т. Д.

Однако, если вы хотите использовать пользовательский обработчикname , оно также должно следовать некоторому соглашению об именах.

Метод должен начинаться с OnPost[Get,...]<Handlername>[Async|NoAsync](its optional).

Таким образом, ваш метод должен быть назван как OnPostAccountChangeAsync()

Если вы определите такой метод, выдолжен сказать представлению, что вы хотите использовать указанный обработчик.Вы говорите это с помощью директивы asp-page-handler, поэтому ваша форма должна выглядеть следующим образом:

<form id="change-password-form" method="post">
   //...
   <button type="submit" class="btn btn-default" asp-page-handler="AccountChange">Submit</button>
</form>


2. Вы связываете свою собственность Input

[BindProperty]
public InputModel Input { get; set; }

Однако в вашем методе OnPostAccountChangeAsync() вы пытаетесь получить доступ к экземпляру параметра типа UserModel, который будет нулевым.Это не связано.В хорошем случае вы получите нулевое исключение.В плохом вы обновите вашу сущность с нулевыми свойствами.Таким образом, ваш метод OnPostAccountChangeAsync() должен принимать в экземпляре параметра InputModel, или вы можете получить доступ к этому свойству непосредственно внутри тела метода (вы можете избавиться от параметра)

OnPostAccountChangeAsync(InputModel Input)
{
 //...
}


3. Небольшая вещь, однако, она улучшает читабельность вашего кода.Пожалуйста, будьте последовательны в именовании ваших переменных.Согласованность делает лучшую ориентацию в вашем коде.В Csharp свойства должны начинаться с заглавной буквы (PascalCasing) .Не стесняйтесь, и проверьте C # соглашение об именах


На ваш вопрос о UserManager в разделе комментариев:
Вы можете посмотреть на Identity какОболочка (точнее сказать API) , которая предоставляет полезные методы для управления пользователями, кроме того, что она предлагает другие вещи.Как я уже сказал, если вы посмотрите на зависимости вашего пакета, вы можете заметить, что Entity Framework поставляется в пакете Identity nuget.Что это значит?Это открывает вам возможность не зависеть только от каких-то «таинственных» Identity.Вы можете явно использовать Entity Framework, например, для сохранения нового пользователя в таблицу AspNetUsers.Четко сказано, вы не ограничены.Однако, если вы уже используете Identity, лучше использовать доступные методы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...