【问题标题】:ASP.NET MVC entity validation error on trying to save database changes尝试保存数据库更改时出现 ASP.NET MVC 实体验证错误
【发布时间】:2016-11-01 23:30:28
【问题描述】:

我一直在尝试完成一个简单的应用程序,我在暑期实习时得到了练习。我几乎没有 ASP.NET 的背景,所以我得到了额外的工作。我正在尝试从 c# 中的 http post 函数获取要更新的数据库条目,但是当函数运行时会引发验证错误。我一直在试图找出错误的原因,但是我似乎无法弄清楚它为什么不起作用。任何帮助表示赞赏。

这是错误:

一个或多个实体的验证失败。有关更多详细信息,请参阅“EntityValidationErrors”属性。 说明:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.Data.Entity.Validation.DbEntityValidationException:一个或多个实体的验证失败。有关详细信息,请参阅“EntityValidationErrors”属性。

来源错误:

第 130 行:db.Entry(productNote).State = EntityState.Modified;

第 131 行:db.SaveChanges();

第 132 行:返回 RedirectToAction("Index");

源文件:C:\Users\Morph\Documents\Visual Studio 2015\Projects\NotesWebApp\NotesWebApp\Controllers\ProductsController.cs 行:131

这是我的控制器中的 http post 功能:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind(Include = "ID,ProductID,NoteText,CreateDate,Archived")] ProductNote productNote)
{
    Response.Write("<script type=\"text/javascript\">alert('Works');</script>");
    if (ModelState.IsValid)
    {
        db.Entry(productNote).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return RedirectToAction("Index");
}

这是我提交给函数的表单:

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(noteItem => note.ID)
    @Html.HiddenFor(noteItem => note.ProductID)
    @Html.HiddenFor(noteItem => note.NoteText)
    @Html.HiddenFor(noteItem => note.CreateDate)
    <div class="checkbox">
        @Html.EditorFor(noteItem => note.Archived)
        @Html.ValidationMessageFor(noteItem => note.Archived, "", new { @class = "text-danger" })
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
}

【问题讨论】:

  • See 'EntityValidationErrors' property for more details告诉你什么。并参考How to create a Minimal, Complete, and Verifiable example。此代码的 90% 与您的问题无关
  • 转到实体验证错误的 msdn 页面很少告诉我为什么会出现问题。我已经访问并尝试查看信息
  • 您需要中断异常并查看 EntityValidationErrors 属性
  • 您好@Ellis,您可以参考this 以帮助您获得准确的错误消息。
  • 那你的方法是错误的。您可以为每个项目创建一个表单,其中只有 ID 的路由值并发布到public ActionResult Archive(int ID)(您可以使用 ajax 执行此操作,以便用户可以继续存档笔记,同时留在同一页面上)

标签: c# asp.net asp.net-mvc


【解决方案1】:

尝试使用

db.Set<ProductNote>().AddOrUpdate(productNote);
db.SaveChanges();

没有

db.Entry(productNote).State = EntityState.Modified;

【讨论】:

  • OP 遇到了 DbEntityValidationException ,这主要是因为一个或多个未正确插入的字段。检查数据库中是否存在记录并不能解决OP问题。
  • 他检查模型是否有效并且它给出了 true 所以我认为验证问题与 id 有关......并且 addOrUpdate 方法负责......这就是我给的原因这个答案
【解决方案2】:

错误的原因是您在foreach 循环中生成表单,因此控件具有与您的模型无关的name 属性(有关更多信息,请参阅HTML Table to ADO.NET DataTable)。因此,您的 POST 方法只是使用默认属性初始化一个新的ProductNote(推测IDint,因此它的值将是0)。

即使您确实正确生成了视图,您也会通过生成大量不必要的 html 并将其发回来降低您的应用程序的性能,但更重要的是,恶意用户可以轻松更改 ProductNote 表中的所有数据而无需你知道的。

从您的 cmets 中,您只想提交一个表单以将单个 ProductNote 标记为已归档。首先创建一个代表你想要做什么的方法

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Archive (int ID)
{
    // Get the original 
    ProductNote model = db.ProductNote.FirstOrDefault(x => x.ID == ID);
    // If the user has the permission to archive and the model is not null
    model.Archived = true;
    db.SaveChanges();
    return RedirectToAction("Index");
}

并将视图更改为

@foreach(var note in Model.ProductNotes)
{
    @Html.DisplayFor(m => note.NoteText)
    ....
    @using (Html.BeginForm("Archive", "Products", new { id = note.ID }))
    {
        @Html.AntiForgeryToken()
        <input type="submit" value="Archive" />
    }
}

您还需要考虑处理表单.submit() 事件以显示确认消息(或者仅使用指向显示确认页面的 GET 方法的链接并从那里进行 POST)。此外,您应该考虑使用 ajax 发布 ID 值,以便您可以留在同一页面上并继续归档更多 ProductNote 项目。

【讨论】:

    【解决方案3】:

    更新实体数据模型将起作用

    【讨论】:

      猜你喜欢
      • 2014-09-05
      • 2012-04-30
      • 2016-07-17
      • 1970-01-01
      • 2017-10-20
      • 2017-11-01
      • 1970-01-01
      • 2014-10-24
      • 2018-05-09
      相关资源
      最近更新 更多