我目前的做法:
视图:
<script language="javascript"> $(function() { $('#editSettings').submit(function () { if ($(this).valid()) { $.ajax({ url: this.action,type: this.method,data: $(this).serialize(),success: function (result) { alert(result); } }); } return false; }); }); </script> [ ... ] @using (Ajax.BeginForm("Edit","Settings",new AjaxOptions {UpdateTargetId = "result"},new { @class = "form-horizontal",@id = "editSettings" } )) { foreach (Setting item in ViewBag.Settings) { @Html.Partial("_SingleSetting",item) } <input type="submit" value="modify" /> }
部分视图加载设置:
<div class="control-group"> <label class="control-label">@settingName</label> <div class="controls"> @Html.EditorFor(model => model.Value) <span class="help-inline">@settingDescription</span> </div> </div>
模型:
[Table("Settings")] public class Setting { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int SettingId { get; set; } public string Name { get; set; } [required(AllowEmptyStrings = true)] [displayFormat(ConvertEmptyStringToNull = false)] public string Value { get; set; } }
我使用ViewBag.Settings = _db.Settings.ToList();设置ViewBag;
jQuery将Data解析为以下方法:
[HttpPost] public ActionResult Edit(IList<Setting> setting) { Console.WriteLine(setting.Count); return Content(""); // Currently for testing purposes only. Breakpoint is set to setting.Count }
有人可以给我一个暗示吗?
关于SO的This主题已经涵盖了在没有Ajax的情况下更新集合.但我不明白这一点.
谢谢您的帮助.
解决方法
naming convention
.
让我们举一个完整的例子(为了简单起见,删除所有噪声,例如Entity Framework):
模型:
public class Setting { public int SettingId { get; set; } public string Name { get; set; } public string Value { get; set; } }
控制器:
public class SettingsController : Controller { public ActionResult Index() { // No idea why you are using ViewBag instead of view model // but I am really sick of repeating this so will leave it just that way ViewBag.Settings = Enumerable.Range(1,5).Select(x => new Setting { SettingId = x,Name = "setting " + x,Value = "value " + x }).ToList(); return View(); } [HttpPost] public ActionResult Edit(IList<Setting> setting) { // Currently for testing purposes only. Breakpoint is set to setting.Count return Content(setting.Count.ToString()); } }
查看(〜/ Views / Settings / Index.cshtml):
@using (Html.BeginForm("Edit",FormMethod.Post,id = "editSettings" })) { foreach (Setting item in ViewBag.Settings) { @Html.Partial("_SingleSetting",item) } <input type="submit" value="modify" /> } @section scripts { <script type="text/javascript"> $('#editSettings').submit(function () { if ($(this).valid()) { $.ajax({ url: this.action,success: function (result) { alert(result); } }); } return false; }); </script> }
设置部分(〜/ Views / Settings / _SingleSetting.cshtml):
@model Setting @{ var index = Guid.NewGuid().ToString(); ViewData.TemplateInfo.HtmlFieldPrefix = "[" + index + "]"; } <input type="hidden" name="index" value="@index" /> <div class="control-group"> <label class="control-label">@Html.LabelFor(x => x.Name)</label> <div class="controls"> @Html.EditorFor(model => model.Value) </div> </div>
注意如何在部分内部更改HtmlFieldPrefix,以便html帮助程序为输入字段生成适当的名称并遵守命名约定.
好吧,现在让我们剪切ViewCrap并正确地做事(当然使用视图模型).
我们一如既往地编写视图模型:
public class Myviewmodel { public IList<Setting> Settings { get; set; } }
然后我们调整控制器:
public class SettingsController : Controller { public ActionResult Index() { var model = new Myviewmodel(); // you will probably wanna call your database here to // retrieve those values,but for the purpose of my example that // should be fine model.Settings = Enumerable.Range(1,Value = "value " + x }).ToList(); return View(model); } [HttpPost] public ActionResult Edit(IList<Setting> setting) { // Currently for testing purposes only. Breakpoint is set to setting.Count return Content(setting.Count.ToString()); } }
查看(〜/ Views / Settings / Index.cshtml):
@model Myviewmodel @using (Html.BeginForm("Edit",id = "editSettings" })) { @Html.EditorFor(x => x.Settings) <input type="submit" value="modify" /> } @section scripts { <script type="text/javascript"> $('#editSettings').submit(function () { if ($(this).valid()) { $.ajax({ url: this.action,success: function (result) { alert(result); } }); } return false; }); </script> }
设置模型的编辑器模板(〜/ Views / Settings / EditorTemplates / Settings.cshtml):
@model Setting <div class="control-group"> <label class="control-label">@Html.LabelFor(x => x.Name)</label> <div class="controls"> @Html.EditorFor(model => model.Value) </div> </div>
现在按惯例工作.无需编写任何foreach循环.索引视图中的@ Html.EditorFor(x => x.Settings)调用分析视图模型的Settings属性,并检测它是某个其他模型的集合(在本例中为Setting).因此它将开始循环遍历此集合并搜索相应的编辑器模板(〜/ Views / Settings / EditorTemplates / Setting.cshtml),该模板将自动为此集合的每个元素呈现.所以你甚至不需要在视图中编写任何循环.除了简化代码之外,编辑器模板中的Html.EditorFor(x => x.Value)现在将为输入字段生成专有名称.