MVC5应用程序:创建身份用户结果无效的模型状态?

时间:2014-06-04 16:27:33

标签: asp.net-mvc asp.net-mvc-5 entity-framework-6 asp.net-identity modelstate

我正在将开发中的应用程序从MVC4 / EF5升级到MVC5 / EF6,以利用(除其他外)ASP.Net Identity。当我尝试创建用户时,我的代码将模型标记为无效而不创建用户。我的视图只是显示一个用于输入电子邮件的框,然后是一个允许登录管理员选择MemberOrganization或Sponsor通过一些下拉菜单分配新用户2的Switch。

我的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);

        }

在我尝试调试此问题时,我按this帖子中的建议添加了errors/errors2个变量。当标记这些属性时,我会收到:

InvalidModelState1

InvalidModelState2

有没有人对此事有一些想法?我以前的代码工作正常,但我仍然习惯使用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()代码行中。我不完全确定我遗失的地方。

EDIT2: 创建()查看[相关]:

@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>

....

3 个答案:

答案 0 :(得分:2)

正如您在最后一张照片中所看到的那样,您在属性 SponsorOrgId 上出现错误,其值为string.Empty(&#34;&#34;)。也许 ApplicationUser 中的 SponsorOrgId 具有 [Requried] 属性。

修改

关于尝试将用户添加到数据库时的问题(当您调用UserManager.Create(用户,密码)时会发生这种情况;

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

然后你可以调试&#34;错误&#34;的值。或者从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 };

答案 1 :(得分:2)

我意识到答复已经很晚了,但在解决这个问题之前,我已经阅读了四个主题。它并不完全明显,它似乎是与自定义属性的继承冲突。我的问题的根源是我创建了一个UserName属性 - 一个自定义属性(......或者我认为)我想要定义为FirstName +&#34; &#34; +姓氏。

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中删除了这行,删除了我的自定义属性, POOF!问题:已解决。我一直将继承定义钻到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.

我擅长遵循指示,所以我添加了新的&#39;关键字(请记住上面的那行我必须注释掉??)。它解决了编译时间CS0114警告,但它阻碍了IUser的用户名。

我相信OP(以及无数其他人)在写这篇文章时做了同样的事情:

var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password };

答案 2 :(得分:1)

如果您的applicationuser类中有用户名和电子邮件属性,则这些属性隐藏了实际属性,因此请从应用程序类中删除它们。这样可以解决问题。