我的主题的开头是here。
使用DropDownList不允许我编辑作者的名字..但是这个解决方案非常好。
我需要修改名称,标题,年份和价格等所有4个字段。
我尝试制作类似复合模型的东西:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
更改我的get方法:
// GET: Books/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
var compModel = new BookAuthorCompositeModel();
compModel.book = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();
compModel.author = dbBooks.Authors.ToList().Where(x => x.Id == id).SingleOrDefault();
return View(bookEdit);
}
它显示我需要的所有内容(我点按"编辑"查看有关名称,标题,年份和价格的信息)。
我的观点是:
@model BookStorage.Models.BookAuthorCompositeModel
@{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Book</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.book.Id)
<div class="form-group">
@Html.LabelFor(model => model.author.AuthorName, "AuthorName", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.author.AuthorName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.author.AuthorName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.book.Title, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.book.Title, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.book.Title, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.book.YearPublish, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.book.YearPublish, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.book.YearPublish, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.book.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.book.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.book.Price, "", new { @class = "text-danger" })
</div>
</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>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
但在Post方法中出现了错误:
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
dbBooks.Entry(BAmodel.book).State = EntityState.Modified;
dbBooks.Entry(BAmodel.author).State = EntityState.Modified;
dbBooks.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
dbBooks.SaveChanges();导致错误(存储更新,插入或删除语句影响了意外的行数(0)。)。我认为使用这种ViewModel有助于编辑所有行,但它不会将数据发送到DB,我无法理解错误。
答案 0 :(得分:2)
如果我理解正确,您想要的是在同一API方法下更新上下文“Book”和上下文“Author”。
为此,首先我要创建一个包含两个对象的ViewModel,这些对象已经存在:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
(这可以修改以用于验证目的,也许可以创建用于验证的新对象。至少,我是这样做的。但是让我们继续。)
现在,您需要在API调用上接收相同的ViewModel,然后使用对象执行所需的操作。为此,我通常对我的上下文进行Get调用,获取要修改的对象。然后我可以自由更新我的上下文:
[HttpPost]
public ActionResult Edit(BookAuthorCompositeModel model)
{
...
}
要获取要修改的对象,取决于您使用的是什么。简单的存储库模式,单元模式,无关紧要。当您获得Book条目时,只需修改它,使用更新功能,我认为它是 dbBooks.BookContext.Update(book),其中“book”是可变的。像这样:
var book = dbBooks.BooksContext.Get(model.Book.BookId);
book.name = "New Name";
dbBooks.BooksContext.Update(book);
dbBooks.SaveChanges();
获取和更新(.Get()和.Update())的方法必须是您正在使用的模式中的方法,但这可能会对您有所帮助。
祝你好运!