c# - 使用 ASP.Net MVC 和实体框架在一个视图中编辑对象和相关对象
问题描述
我正在创建一个应用程序,可以在其中创建注释并且可以将一对多的部件添加到注释中。(该应用程序适用于客户要求拖拉机零件的拖拉机打捞场)。我知道以前有人问过类似的问题。但是我找不到任何与我在 EF 和所有方面的情况非常相关的东西。
在一个视图中创建/编辑带有其部分的注释时遇到了很多困难。不过,我想专注于编辑这个问题。
我有两个具有关系的简单 CLR 类。
public class Note
{
public int ID { get; set; }
public string CustomerName { get; set; }
public string CustomerPhone { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public string CreatedBy { get; set; }
public string AssignedTo { get; set; }
public virtual ICollection<Part> Parts { get; set; }
}
public class Part
{
public int PartID { get; set; }
public string PartNumber { get; set; }
public string Description { get; set; }
public int NoteID { get; set; }
public virtual Note Note { get; set; }
}
和 DbContext:
public class CallNoteContext : DbContext
{
public CallNoteContext() { }
public DbSet<Note> Notes { get; set; }
public DbSet<Part> Parts { get; set; }
}
我的问题是将两个实体的数据绑定到编辑视图,访问视图中的数据以进行编辑并将注释和多个部分保存到 httppost 操作中的数据库。
我已经尝试了很多东西,但是在阅读了很多文章之后,我不断地回到这个控制器和视图。对我来说,这似乎应该有效。但显然我错过了一些东西。
这是来自我的控制器的编辑和发布操作。
private CallNoteContext db = new CallNoteContext();
// GET: Note/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Note note = db.Notes.Find(id);
var model = new Note()
{
CustomerName = note.CustomerName,
CustomerPhone = note.CustomerPhone,
DateCreated = note.DateCreated,
DateUpdated = note.DateUpdated,
CreatedBy = note.CreatedBy,
AssignedTo = note.AssignedTo,
Parts = note.Parts
};
if (note == null)
{
return HttpNotFound();
}
return View(model);
}
// POST: Note/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,CustomerName,CustomerPhone,DateCreated,DateUpdated,CreatedBy,AssignedTo,Parts")] Note note)
{
if (ModelState.IsValid)
{
foreach(var p in note.Parts)
{
db.Entry(p).State = EntityState.Modified;
db.SaveChanges();
}
db.Entry(note).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(note);
}
当我尝试在下面的视图中为 p.PartNumber 和 p.Description 制作编辑器时,它会中断,但找不到这些属性。我有一种感觉,我在控制器的“获取”操作中做错了什么。但我很难弄清楚出了什么问题。
顺便说一句,IntelliSense 表示控制器未发现任何问题。
这是我的编辑视图。
@model CallNote.Models.Note
<head>
<script src="~/Scripts/jquery-3.4.1.js" type="text/javascript"></script>
</head>
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.HiddenFor(model => model.ID)
<div class="form-group">
@Html.LabelFor(model => model.CustomerName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CustomerName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CustomerPhone, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CustomerPhone, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CustomerPhone, "", new { @class = "text-danger" })
</div>
</div>
@*There are editors here for all of the properties, but I didn't list them to save space.*@
@*The app always breaks when it gets to this foreach because it says it can't find p.PartNumber. What is wrong?
@foreach (var p in Model.Parts)
{
<div>
@*I also tried just using p.PartNumber, but it says p doesn't exist in current context.
@Html.EditorFor(p => p.PartNumber)
@Html.EditorFor(p => p.Description)
</div>
}
<div id="partInfo" style="display:none">
@Html.EditorFor(p => p.PartNumber)
@Html.EditorFor(p => p.Description)
</div>
<div id="btnWrapper">
<input id="btnAddPart" type="button" value="Add Part" />
</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>
}
@*The script below works, allowing you to add part editors*@
<div>
@Html.ActionLink("Back to List", "Index")
</div>
<script>
$(document).ready(function () {
$("#btnAddPart").click(function () {
var partinfo = $("#partInfo").html();
$("#partInfo").append(partinfo);
});
});
</script>
我也不确定 httppost 操作是否有效。我还不能尝试它,因为我什至无法加载编辑视图。因此,如果您对此也有任何建议,请告诉我。
我刚刚开始使用MVC,所以详细的答案会很棒!
解决方案
您必须在注释中包含部分
....
Note note = db.Notes
.Include(i=> i.Parts)
.FirstOrDefault(i=>i.ID==id);
if (note == null)
{
return HttpNotFound();
}
.....
并且由于您使用的是编辑器,因此将 foreach 循环替换为 for 循环
@if( Model.Parts!=null && Model.Parts.Count >0)
{
@for (var i=0; i< Model.Parts.Count; i++)
{
<div id="partInfo" style="display:none">
@Html.EditorFor(model => model.Parts[i].PartNumber)
@Html.EditorFor(model => model.Parts[i].Description)
</div>
...... and so on for all properties
}
}
并从动作中删除绑定
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Note note)
{
if (!ModelState.IsValid) return View(note);
var existedNote = db.Notes
.Include(i=> i.Parts)
.FirstOrDefault(i=>i.ID==note.ID);
if(existedNote!=null)
{
db.Entry(existedNote).CurrentValues.SetValues(note);
if(note.Parts!=null && note.Parts.Count > 0)
{
foreach( var part in note.Parts)
{
var existingPart = existingNote.Parts.FirstOrDefault(p => p.PartID == part.PartID);
if (existingPart == null)
{
existingNote.Parts.Add(part);
}
else
{
context.Entry(existingPart).CurrentValues.SetValues(part);
}
}
}
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(note);
}
````
推荐阅读
- reactjs - 在 safari 和 chrome 中调整窗口高度时保持图像的纵横比
- java - 如何在 SQLite 中插入和检索数据?
- kubernetes - 无法挂载卷 /dev/rbd1 [xfs]
- android - 如何在片段中的浮动操作按钮中打开链接
- bitwise-and - if(e & 1) 在python中是什么意思?
- python - json.loads 因 JSONDecodeError 失败:期望值
- batch-file - 如何使用 WMIC 从远程服务器启动应用程序
- java - DefaultServlet 的问题
- pointers - 如何将函数的结果作为派生类型类的元素?
- angularjs - $http 偶尔会因 ERR_EMPTY_RESPONSE 而失败