MVC5应用:创建身份用户结果处于无效模型状态?
-
21-12-2019 - |
题
我正在将开发中的应用程序从 MVC4/EF5 升级到 MVC5/EF6,以利用(除其他外)ASP.Net Identity。当我尝试创建用户时,我的代码将模型标记为无效并且不创建用户。我的视图只是显示一个用于输入电子邮件的框,然后显示一个开关,让登录的管理员选择会员组织或赞助商以通过一些下拉菜单分配新用户 2。
我的 UserController 的 Create() 方法如下:
// 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。
编辑:正如 Rikard 所建议的,我已经设置了模型,其中 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>
....
解决方案
正如您在最后一张图片中看到的,您的房产有错误 赞助商组织ID 其值为 string.Empty ("")。也许是 赞助商组织ID 在 应用程序用户 有 [必填] 属性。
编辑
关于尝试将用户添加到数据库时出现的问题(当您调用 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);
}
然后您可以调试“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.
我擅长遵循说明,因此我添加了“new”关键字(还记得上面我必须注释掉的那一行...?)。它解决了编译时CS0114警告,但它阻碍了IUser的用户名。
我相信,OP(以及无数其他人)在写下以下内容时也做了同样的事情:
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password };
如果您的 applicationuser 类中有用户名和电子邮件属性,这些属性隐藏了实际属性,因此将它们从您的应用程序类中删除。这将解决问题。