我的应用程序中有一个非常庞大的表单,我的模型中有很多不同的输入和很多列表。所以我会尝试添加/删除列表而不将完整的模型发送到服务器。
我现在尝试了几种方法,但我找不到干净的方法。你可以想象我的模型:
public class EditSomething
{
public string name { get; set;}
public List<something> somethingList { get; set;}
// a lot other fields...
public EditSomething(EditSomethingFromDatabase editSomethingFromDatabase)
{
name = editSomethingFromDatabase.Name;
somethingList = new List<SomethingModel>();
foreach(var something in editSomethingFromDatabase.Something)
{
somethingList.Add(new SomethingModel(editSomethingFromDatabase.Something));
}
}
}
另一个模型看起来很相似但没有列表。
在视图中我有一个模型表:
<h2>Something</h2>
<div id="SomethingDiv">
<table id="SomethingTable">
<thead>
<tr>
<th>@Html.Label("SomethingName")</th>
<th>@Html.Label("SomethingID")</th>
<th></th>
</tr>
</thead>
<tbody id="SomethingTableBody">
@Html.EditorFor(x => x.somethingList)
</tbody>
</table>
<p>
<input type="button" name="addSomething" value="Add Something" id="AddSomething">
</p>
</div>
addSomething的jquery是:
$('#AddSomething').click(function () {
$.ajax({
url: '@Url.Action("AddSomething", "SomethingModels")',
data: { tableSize: $('#SomethingTable tr').length },
cache: false,
success: function (html) { $('#SomethingTable tr:last').after(html); }
});
控制器方法AddSomething是:
public ActionResult AddSomething (int tableSize)
{
SomethingModel something= new SomethingModel(null, (-2) * (tableSize + 1));
return PartialView(""~/Views/EditorTemplates/EditSomethingModel.cshtml"", something);
}
至少我在EditorTemplates中有一个编辑器模板和editorfor和partialview。这有我想要发送到服务器的重要信息:
@model SomethingModel
<tr>@TextBoxFor(m=>m.SomethingName)<td>
@TextBoxFor(M =&GT; m.SomethingID)
现在问题是,第一个视图的提交仅将SomethingModel
发布到打开视图时已存在的服务器,但AddMutation
方法中的新SomethingModel不在这篇文章。有人想解决这个问题吗?
修改:更改了编辑器模板的路径,因此我只需要EditorFor
和PartialView
的一个视图。
Edit2:为解决主要问题,我创建了一个如下视图,并将其用作局部视图。现在数据正确地发送到服务器。只有客户端的验证仍然无效:
@model SomethingModel
<tr>@TextBoxFor(m=>m.SomethingName, new{Name="somethingList["+ViewBag.ListId+"].SomethingName")<span class="field-validation-valid" data-valmsg-for="somethingList[@ViewBag.ListId].SomethingName" data-valmsg-replace="true"></span><td>
<tr>@TextBoxFor(m=>m.SomethingID, new{Name="somethingList["+ViewBag.ListId+"].SomethingID")<span class="field-validation-valid" data-valmsg-for="somethingList[@ViewBag.ListId].SomethingID" data-valmsg-replace="true"></span><td>
</tr>
在AddSomething
方法中,我添加了ViewBag.ListId
,其中包含列表中下一个元素的ID。
答案 0 :(得分:2)
这似乎是一个合理的方法,但你没有展示你的EditorTemplate,所以我将假设它的东西:
@model List<something>
@for(int i = 0; i < Model.Count; i++)
{
<tr>
<td>@Html.DisplayFor(m => m[i].Id) @Html.HiddenFor(m => m[i].Id)</td>
<td>@Html.EditorFor(m => m[i].Name)</td>
</tr>
}
你的ajax方法应该返回一行的HTML - 这很重要......表单字段需要在表格的最后一个上面命名为1。
因此,当您查看表的渲染源时(在添加任何新字段之前,它可能看起来像:
...
<tbody>
<tr>
<td>1 <input type="hidden" name="something[0].Id" value="1"/></td>
<td><input type="text" name="something[0].Name" value="somename" /></td>
</tr>
</tbody>
您需要确保新行的ajax方法返回的html为:
<tr>
<td>2 <input type="hidden" name="something[1].Id" value="2"/></td>
<td><input type="text" name="something[1].Name" value="somenewname" /></td>
</tr>
即。括号内的数字是某个项目中的下一个索引。如果索引中存在间隙(或它们重叠),则不会解析新项目。
编辑 - 要使客户端验证适用于新字段,请更改jquery ajax成功回调,如下所示:
$('#AddSomething').click(function () {
$.ajax({
url: '@Url.Action("AddSomething", "SomethingModels")',
data: { tableSize: $('#SomethingTable tr').length },
cache: false,
success: function (html) {
$('#SomethingTable tr:last').after(html);
$.validator.unobtrusive.parse('#SomethingTable');
}
});