Приложение MVC5:Создание идентификационного пользователя приводит к недопустимому состоянию модели?
-
21-12-2019 - |
Вопрос
Я обновляю приложение в разработке с MVC4/EF5 до MVC5/EF6, чтобы использовать (помимо прочего) ASP.Net Identity.Когда я пытаюсь создать пользователя, мой код помечает модель как недействительную и не создает пользователя.My View просто отображает поле для ввода адреса электронной почты, а затем переключатель, который позволяет вошедшему в систему администратору выбрать либо организацию-члена, либо спонсора для назначения нового пользователя 2 через некоторые раскрывающиеся списки.
Метод Create() моего UserController приведен ниже:
// GET: Admin/UserManagement/Create
public ActionResult Create()
{
ViewBag.headerTitle = "Create User";
ViewData["Organization"] = new SelectList(db.MemberOrganizations, "Id", "Name");
ViewData["Sponsor"] = new SelectList(db.SponsorOrganizations, "Id", "Name");
ViewBag.SwitchState = true;
ApplicationUser newUser = new ApplicationUser();
newUser.RegisteredDate = DateTime.Now;
newUser.LastVisitDate = DateTime.Now;
newUser.ProfilePictureSrc = null;
return View(newUser);
}
// POST: Admin/UserManagement/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Property1, Property2, etc.")] ApplicationUser applicationUser)
{
if (ModelState.IsValid)
{
ViewBag.headerTitle = "Create User";
PasswordHasher ph = new PasswordHasher();
var password = ph.HashPassword("aR@nD0MP@s$w0r9");
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password };
IdentityResult result = await UserManager.CreateAsync(user, user.PasswordHash);
if (result.Succeeded)
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
else
{
ModelState.AddModelError("", "Failed to Create User.");
}
}
ModelState.AddModelError("", "Failed to Create User.");
var errors = ModelState.Where(x => x.Value.Errors.Count > 0).Select(x => new { x.Key, x.Value.Errors }).ToArray();
var errors2 = ModelState.Values.SelectMany(v => v.Errors);
ViewData["Organization"] = new SelectList(db.MemberOrganizations, "Id", "Name", applicationUser.MemberOrgId);
ViewData["Sponsor"] = new SelectList(db.SponsorOrganizations, "Id", "Name", applicationUser.SponsorOrgId);
if (applicationUser.MemberOrgId != null)
{
ViewBag.SwitchState = true;
}
else
{
ViewBag.SwitchState = false;
}
ViewBag.OrganizationId = new SelectList(db.MemberOrganizations, "Id", "State", applicationUser.MemberOrgId);
// If we got this far, something failed, redisplay form
return View(applicationUser);
}
В моих попытках отладить проблему я добавил errors/errors2
переменные, как предложено в этот почта.Перейдя к свойствам состояния модели, когда они помечены, я получаю:
Есть ли у кого-нибудь мысли по этому поводу?Мой предыдущий код работал нормально, но я все еще использую ASP.Net Identity.
РЕДАКТИРОВАТЬ:Как предложил Рикард, я установил свою модель, в которой SponsorOrgID и MemberOrgID не требуются (только 1).Теперь мой код обрабатывается до следующего сегмента:
var user = new ApplicationUser() { Name = applicationUser.Name, Email = applicationUser.Email, PasswordHash = password };
IdentityResult result = await UserManager.CreateAsync(user, user.PasswordHash);
if (result.Succeeded) // ERROR
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
Когда я проверяю значение result
и перейти к Errors->[string[]]->[0]
сообщение об ошибке: Name cannot be null or empty
.У кого-нибудь есть мысли по этому поводу?Я добавил поле в свое представление, чтобы указать новых пользователей. Name
и включил его в вышеизложенное new ApplicationUser()
строка кода.Я не совсем уверен, где мне что-то не хватает.
РЕДАКТИРОВАТЬ2:Представление Create() [Соответствует]:
@model PROJECTS.Models.ApplicationUser
@{
ViewBag.Title = "Create";
Layout = "~/Areas/Admin/Views/Shared/_LayoutAdmin.cshtml";
string cancelEditUrl = "/Admin/UserManagement/";
}
@using (Html.BeginForm("Create", "UserManagement", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.RegisteredDate)
<div class="container">
<div class="row">
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field" style="margin-bottom: 15px">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="row">
<div class="editor-label">
@Html.LabelFor(model => model.Email)
</div>
<div class="editor-field" style="margin-bottom: 15px">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
....
Решение
Как вы можете видеть на последней фотографии, у вас есть ошибка в объекте размещения. СпонсорОргид который имеет значение string.Empty ("").Может быть, СпонсорОргид в Пользователь приложения имеет [Обязательно] атрибут.
РЕДАКТИРОВАТЬ
Что касается вашей проблемы при попытке добавить пользователя в базу данных (это произошло, когда вы вызывали UserManager.Create(user,password);
IdentityResult result = await UserManager.CreateAsync(user, user.PasswordHash);
if (result.Succeeded)
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
else
{
var errors = string.Join(",", result.Errors);
ModelState.AddModelError("", errors);
}
Затем вы можете отладить значение «ошибок» или прочитать сообщение об ошибке из вашего ModelState.
Что касается вашего РЕДАКТИРОВАТЬ
Добавьте имя к этой части:
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password, Name = applicationUser.Name };
РЕДАКТИРОВАТЬ 2Проблема в том, что невозможно создать пользователя без имени пользователя.Но вы можете добавить адрес электронной почты пользователя к имени пользователя.А затем измените его на указанное пользователем имя пользователя.Чтобы пройти проверку, вам необходимо добавить эту часть.
UserManager.UserValidator = new UserValidator<User>(UserManager) { RequireUniqueEmail = true };
Другие советы
Я понимаю, что уже поздно отвечать, но я прочитал четыре темы, прежде чем решить эту проблему.Это не совсем очевидно и похоже на конфликт наследования с пользовательскими свойствами.Корнем моей проблемы было создание свойства UserName - пользовательского свойства (... или я так думал), которое я хотел определить как FirstName + " " + LastName.
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
// public new string UserName { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
...remainder removed for clarity.
Как только я закомментировал эту строку из IdentityModels.cs, которая удалила мое пользовательское свойство, ПУФ! Проблема:решено.Я подробно изучил определения наследования вплоть до IUser[TKey] и нашел то, что, по моему мнению, было корнем моей (нашей) проблемы.
namespace Microsoft.AspNet.Identity
{
// Summary:
// Minimal interface for a user with id and username
//
// Type parameters:
// TKey:
public interface IUser<out TKey>
{
// Summary:
// Unique key for the user
TKey Id { get; }
//
// Summary:
// Unique username
string UserName { get; set; }
}
}
Я знал, что в класс ApplicationUser можно добавлять собственные свойства, но не знал, что уже используются конкретные имена свойств, не определенные в этом классе.Первоначально, добавив поле UserName просто как общедоступную строку, я получил следующее:
[...] warning CS0114: 'MyApp.Models.ApplicationUser.UserName' hides inherited member 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser<string,Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin,Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole,Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim>.UserName'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
Я хорошо следую инструкциям, поэтому добавил ключевое слово «новое» (помните ту строку выше, которую мне пришлось закомментировать...?).Это решило предупреждение CS0114 во время компиляции, но заблокировало имя пользователя IUser.
Я полагаю, что ОП (и многие другие) сделал то же самое, когда написал это:
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password };
Если у вас есть свойства имени пользователя и электронной почты в классе applicationuser, эти свойства скрывают фактические свойства, поэтому удалите их из класса приложения. Это решит проблему.