无法保存对Identity User的更改?

时间:2014-06-10 13:28:16

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

我已经创建了MVC5 / EF6应用程序的Admin部分。我可以成功创建Create()和Delete()用户,但我的Edit()继续在POST上出错。

修改视图

@model PROJECT.Models.ApplicationUser

@{
    ViewBag.Title = "Edit";
    Layout = "~/Areas/Admin/Views/Shared/_LayoutAdmin.cshtml";
    PROJECT.Helper.GeneralHelper helper = new PROJECT.Helper.GeneralHelper();
    string cancelEditUrl = "/Admin/UserManagement/";
}

@using (Html.BeginForm("Edit", "UserManagement", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.Id)
    @Html.HiddenFor(model => model.ForumUsername)
    @Html.HiddenFor(model => model.ReceiveSystemEmails)
    @Html.HiddenFor(model => model.RegisteredDate)
    @Html.HiddenFor(model => model.LastVisitDate)

    <div class="container">
        <div class="row">
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>

            <div class="editor-field">
                @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.Position)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Position, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Position)
            </div>
        </div>

        <div class="row">
            <div class="editor-label">
                @Html.LabelFor(model => model.Email)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Email)
            </div>
        </div>

        <div class="row">
            <div class="editor-label">
                @Html.LabelFor(model => model.PhoneNumber)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.PhoneNumber, new { @class = "form-control", type = "tel" })
                @Html.ValidationMessageFor(model => model.PhoneNumber)
            </div>
        </div>

        <div class="row">
            <div class="col-md-1" style="padding-left: 0px">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
            <div class="col-md-9" style="padding-left: 0px">
                <a href="@cancelEditUrl" class="btn btn-danger">Cancel</a>
            </div>

            @{
                string deleteURL = "/Admin/UserManagement/Delete/" + Model.Id;
            }
            <a href=@deleteURL class="btn btn-danger col-md-2">
                <span class="glyphicon glyphicon-minus"></span> Delete User
            </a>
        </div>
  </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

控制器

    // GET: Admin/UserManagement/Edit/5
    public async Task<ActionResult> Edit(string id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        ApplicationUser model = await UserManager.FindByIdAsync(id);
        if (model == null)
        {
            return HttpNotFound();
        }
        return View(model);
    }

    // POST: Admin/UserManagement/Edit/5
    // 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> Edit([Bind(Include = "Id,property1, property2, etc...")] ApplicationUser applicationUser)
    {
        if (ModelState.IsValid)
        {
            db.Entry(applicationUser).State = EntityState.Modified;
            await db.SaveChangesAsync();
            return RedirectToAction("Index");
        }
        return View(applicationUser);
    }

当我创建用户时,我必须输入Name&amp; GUI侧的Email,例如Test Usertestuser@project.org。创建用户后,我将返回“索引”视图,在该视图中,我可以选择“编辑新用户”。如果我打开编辑视图然后添加说Test Monkey的位置并单击保存,我的Controller的POST编辑()代码会执行,但在await db.SaveChangesAsync();会立即跳转到我的DB dispose():

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }

我继续从那里得到以下错误详情:

Server Error in '/' Application.

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

任何人都有关于可能发生的事情的想法?这是以前在MVC4 / EF5下开发的项目的一个功能部分,然后升级为使用MVC5中的增强功能,如身份。

修改

按照David Martin的建议实施了应用程序跟踪:

Validation failed for one or more entities while saving changes to SQL Server Database using Entity Framework

View ASP.Net Trace Information Application Trace

不太确定我现在正在寻找什么?

EDIT2

仍然不确定我究竟是在追踪Trace之后,但是在Catch中使用我的断点我深入到[dbEx]并发现真正的错误消息是“ UserName字段是必需的

dbException

通过添加applicationUser.UserName = applicaitonUser.Email(与我当前的应用程序中的内容相同),我现在可以编辑并保存对用户的更改。

然而,我似乎无法弄清楚,这就是为什么首先需要这样做的原因。如下所示(我已经确认),用户的[UserName]值在我的POST Create()方法中设置:

    // 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 = "Id,property1,property2,etc.,UserName")] ApplicationUser applicationUser)
    {
        if ((applicationUser.MemberOrgId == null) && (applicationUser.SponsorOrgId == null))
        {
            ModelState.AddModelError("", "Must select either an Organization or Sponsor from the dropdown lists.");
            return View(applicationUser);
        }

        if (ModelState.IsValid)
        {
            ViewBag.headerTitle = "Create User";
            applicationUser.UserName = applicationUser.Email;
            IdentityResult result = await UserManager.CreateAsync(applicationUser, "test12345");
            if (result.Succeeded) 
            {
                await db.SaveChangesAsync();
                return RedirectToAction("Index", "UserManagement");
            }
            else
            {
                ModelState.AddModelError("", "Failed to Create User.");
                var errors = string.Join(",", result.Errors);
                ModelState.AddModelError("", errors);
            }
        }

        ModelState.AddModelError("", "Failed to Create User.");
        var errors1 = ModelState.Where(x => x.Value.Errors.Count > 0).Select(x => new { x.Key, x.Value.Errors }).ToString();
        ModelState.AddModelError("", errors1);

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

因此,它不应该在我的POST Edit()中被标记为已经设置好了吗?

1 个答案:

答案 0 :(得分:0)

不确定我是否有误,但您似乎没有将View中的UserName保留为modelbound(例如,使用@Html.HiddenFor(x=>x.UserName)。 此外,在您的POST操作中检查applicationUser.UserName = applicationUser.Email; 后,if (ModelState.IsValid)中的UserName似乎设置为