尝试保存数据库更改时ASP.NET MVC实体验证错误

时间:2016-06-30 03:22:15

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

我一直在努力完成一个简单的应用程序,我在暑期实习时给予了练习。我几乎没有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(“索引”);

     

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

这是我的Controller中的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>
}

3 个答案:

答案 0 :(得分:1)

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

即使您确实生成了正确的视图,您也会通过生成大量不必要的HTML并将其发回来降级您的应用,但更重要的是,恶意用户可以轻松更改ProductNote中的所有数据你不知道的桌子。

根据您的评论,您只想提交一个表单,将单个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个项目。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

尝试使用

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

$(document)
    .on('click.bs.dropdown.data-api', clearMenus)
    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)

}(jQuery);