【问题标题】:Cannot save changes to Identity User?无法保存对身份用户的更改?
【发布时间】:2014-06-10 13:28:16
【问题描述】:

我已经为我的 MVC5/EF6 应用程序创建了一个管理部分。我可以成功地 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);
    }

创建用户时,我只需在 GUI 端输入 NameEmail,例如 Test Usertestuser@project.org。创建用户后,我将返回到我的索引视图,在这里我可以选择编辑我的新用户。如果我打开我的编辑视图,然后添加一个位置为Test Monkey 并单击保存,我的控制器的 POST Edit() 代码将执行,但在await db.SaveChangesAsync(); 处会立即跳转到我的数据库 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 中的增强功能,例如 Identity。

编辑

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

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

View ASP.Net Trace Information

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

EDIT2

仍然不确定我到底在跟踪什么,但使用我在 Catch 中的断点深入 [dbEx] 并发现真正的错误消息是“用户名字段是必需的 ”。

通过添加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() 中按要求标记,因为它已被设置?

【问题讨论】:

  • 能不能在debug中运行,看看能不能捕捉到抛出的异常?
  • 您检查过 EntityValidationErrors 属性吗?答案就在那里。
  • @PseudoNym01 我在我的 Edit POST 方法中添加了一个 try-catch:return Json(new { error = ex.Message + ",\n" + ex.InnerException + ",\n" + ex.Data + ",\n" + ex.Source }); 这将返回:{"error":"Validation failed for one or more entities. See \u0027EntityValidationErrors\u0027 property for more details.,\n,\nSystem.Collections.ListDictionaryInternal,\nEntityFramework"}。这有帮助吗? @Ozz 我一直在尝试弄清楚如何检查该特定属性,但还没有运气。
  • 见这里 EntityValidationErrors - stackoverflow.com/questions/5400530/…
  • @DavidMartin,谢谢!我环顾四周,但始终找不到要使用的命名空间 :) 这可能是一个愚蠢的问题,但我在哪里/如何查看收集的 Trace.TraceInformation()

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


【解决方案1】:

不确定我是否弄错了,但您似乎没有将视图中的用户名保留为模型绑定(例如,通过使用 @Html.HiddenFor(x=&gt;x.UserName). 此外,applicationUser.UserName = applicationUser.Email; 中的用户名似乎是在 您在 POST 操作中检查了 if (ModelState.IsValid) 之后设置的?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多