我有一个项目,我使用EntityFramework Code First来管理数据库。 我正在使用的模型如下:
[Table("Data")]
public class Data
{
[Key, Column("Id")]
public int Id { get; set; }
[Column("Code")]
public string Code { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Description")]
public string Description { get; set; }
public virtual List<DataAttribute> Attributes { get; set; }
}
和
[Table("DataAttribute")]
public class DataAttribute
{
[Key, Column("Id")]
public int Id { get; set; }
[Column("IdData"), ForeignKey("Data")]
public int IdData { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Description")]
public string Description { get; set; }
public virtual Data Data { get; set; }
}
我遇到的问题是当我尝试编辑Data对象(及其相关的DataAttribute值)时。在提交包含Data元素和DataAttribute元素的表单时,我还没有正确映射它。我举了一个.cshtml文件的例子。
@model MVCTestApp.Models.Data
@{
ViewBag.Title = "Edit";
}
@section Scripts {
<script type="text/javascript">
$(function () {
$('#new-row').click(function () {
$('table tbody').append(
'<tr>' +
'<td><input class="name" type="text" /></td>' +
'<td><input class="description" type="text" /></td>' +
'<td><a class="delete" href="#">Delete</a></td>' +
'</tr>'
);
$('.delete').click(function () {
$(this).parent().parent().remove();
});
});
});
</script>
}
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) {
@Html.HiddenFor(a => a.Id)
Name:
<br />
@Html.TextBoxFor(a => a.Name)
<br />
Description:
<br />
@Html.TextBoxFor(a => a.Description)
<br />
Code:
<br />
@Html.TextBoxFor(a => a.Code)
<br />
<table>
<thead>
<tr>
<th>
Name
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a id="new-row" href="#">New Row</a>
</td>
<td colspan="2">
</td>
</tr>
@if (Model != null) {
foreach (var item in Model.Attributes) {
<tr>
@Html.HiddenFor(b => item.Id)
@Html.HiddenFor(b => item.IdData)
<td class="name">@Html.TextBoxFor(b => item.Name)
</td>
<td class="description">@Html.TextBoxFor(b => item.Description)
</td>
<td>
<a class="delete" href="#">Delete</a>
</td>
</tr>
}
}
</tbody>
</table>
<input type="submit" value="submit" />
}
问题是这个。
如何在发布时让EntityFramework识别Controller上的DataAttributes列表?
这是我现在正在使用的代码。
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Data model)
{
if (model != null) {
db.Data.Add(model); //model has the model.Attributes list set as null
db.SaveChanges();
return View("Index", db.Data.OrderBy(a => a.Id).ToList());
}
return View();
}
提前谢谢。
答案 0 :(得分:0)
首先,你需要了解一些事情。 第一个问题是,为什么代码第一?您没有理由不构建sql模型并使用EF工具导入。 然后,您需要了解ModelBinder机制的工作原理。您发送带有参数的http post请求,每个参数都带有一个名称,并希望将其绑定到Model类。 ModelBinder试图在Model类中找到这些名称,如果你有大量具有相同名称的参数,它们将永远不会发生。此类属性也称为导航属性,它们应由EF或以分开的形式加载。
例如,您正在尝试使用一个表单来构建具有许多DataAttributes的Data对象。为什么不首先创建Data对象,然后在另一个视图中添加DataAttibutes? 那就是MVC的全部意义。不同的型号 - &gt;不同的控制器 - &gt;不同的观点。
如果你没有分开责任,你将面临更多麻烦。
答案 1 :(得分:0)
为了解决这个问题,我做了以下操作:将视图上的foreach更改为for并使用Attributes [i],以便它可以使用它来创建输入(这是使Controller实际接收值的原因)和我还改变了创建新行的方式,以便它们也使用相同的命名约定并传递给控制器。
以下是新观点:
@model MVCTestApp.Models.Data
@{
ViewBag.Title = "Edit";
}
@section Scripts {
<script type="text/javascript">
$(function () {
$('#new-row').click(function () {
var counter = $("#counter").val();
counter++;
$('table tbody').append(
'<tr>' +
'<td><input id="Attributes_' + counter + '__Name" ' +
'name="Attributes[' + counter + '].Name" type="text" /></td>' +
'<td><input id="Attributes_' + counter + '__Description" ' +
'name="Attributes[' + counter + '].Description" type="text" /></td>' +
'<td><a class="delete" href="#">Delete</a></td>' +
'</tr>'
);
$('.delete').click(function () {
$(this).parent().parent().remove();
});
$("#counter").val(counter);
});
});
</script>
}
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) {
var counter = 0;
@Html.HiddenFor(a => a.Id)
Name:
<br />
@Html.TextBoxFor(a => a.Name)
<br />
Description:
<br />
@Html.TextBoxFor(a => a.Description)
<br />
Code:
<br />
@Html.TextBoxFor(a => a.Code)
<br />
<table>
<thead>
<tr>
<th>
Name
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a id="new-row" href="#">New Row</a>
</td>
<td colspan="2">
</td>
</tr>
@if (Model != null) {
for (int i = 0; i < Model.Attributes.Count; i++) {
<tr>
@Html.HiddenFor(a => a.Attributes[i].Id)
@Html.HiddenFor(a => a.Attributes[i].IdData)
<td>@Html.TextBoxFor(a => a.Attributes[i].Name)</td>
<td>@Html.TextBoxFor(a => a.Attributes[i].Description)</td>
<td>
<a class="delete" href="#">Delete</a>
</td>
</tr>
counter = i;
}
}
</tbody>
</table>
<input type="submit" value="submit" />
@Html.Hidden("counter", counter.ToString());
}