我无法将使用局部视图动态创建的子复杂对象集合绑定到视图模型IEnumerable
属性。
我已经使用在本博客https://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/上发现的技术,成功地将使用局部视图动态创建的对象绑定到视图模型。我采用了相同的技术,但是无法将集合绑定到视图模型中的IEnumerable
属性。
[BindRequired]
public class EmployeeViewModel
{
other properties....
public IEnumerable<ContactDetailViewModel> EmployeeContact { get; set; }
}
[BindRequired]
public class ContactDetailViewModel
{
// I use this as my indexer for dynamic elements
public string RecordId { get; set; } = Guid.NewGuid().ToString();
public string Telephone { get; set; }
public string EmailAddress { get; set; }
public string ContactDescription { get; set; }
}
我通过ajax调用此操作方法以添加动态联系人详细信息元素,并将部分视图返回为html,并且效果很好。
[Route("[action]", Name = "BlankEmployeeContactDetail"), HttpGet("AddBlankContactDetail")]
public PartialViewResult AddBlankContactDetail()
{
return PartialView("_ContactInformation", new ContactDetailViewModel());
}
可使用以下方法将初始联系人详细信息添加到主视图,请按照此链接https://1drv.ms/u/s!AkRSHVUtFlKhuHaxH96Ik4ineATE下载主视图和部分视图cshtml文件。还值得一提的是,当我包含此局部视图时,模型绑定对于所有其他属性都将失败,但是在注释掉它时它会起作用。我感到困惑,非常感谢您能负担得起我的任何帮助。
<section id="widget-grid" class="">
<div class="row contactContainer">
@{ await Html.RenderPartialAsync("_ContactInformation", new ContactDetailViewModel()); }
</div>
</section>
这是我尝试将发布的数据绑定到的控制器操作方法:
[Route("[action]"), HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public IActionResult Register([FromForm] EmployeeViewModel model, [FromQuery] string returnUrl = null)
{
if (ModelState.IsValid)
{
}
return View(model);
}
答案 0 :(得分:1)
为了进行绑定,输入名称要遵循一个特定的约定,该约定映射到您要绑定的对象。尽管您的问题尚不清楚,但我最好的猜测是您正在尝试最终绑定到EmployeeViewModel
的实例,这意味着您的联系信息输入将需要使用以下名称:EmployeeContact[0].Telephone
,但是当您将ContactDetailViewModel
的实例作为部分视图的“模型”传递时,名称将仅为Telephone
,更糟糕的是,这些相同的名称将一遍又一遍地重复,即的每个联系人信息集您创建的字段都将有一个仅名为Telephone
的输入。
总之,您需要整个模型的上下文来生成正确的输入名称。您有两种选择。
由于您是通过AJAX请求检索字段集的,因此可以将“前缀”与该请求一起使用。换句话说,您可以跟踪索引值,计算已添加的节数,然后与对新节的请求一起发送
prefix: 'EmployeeContact[' + (i + 1) + ']',
然后,在您的部分视图中:
@{ await Html.RenderPartialAsync("_ContactInformation", new ContactDetailViewModel(), new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = ViewBag.Prefix } } ); }
这有点怪癖,不过老实说可能很容易出错。更好的选择是采用完全不同的方法。无需回叫以获得局部视图,只需将其定义为模板一次即可:
<script type="text/html" id="ContactInformationTemplate">
<!-- HTML for contact information inputs -->
</script>
然后,使用Vue,React,Angular等库,您可以设置绑定到特定JavaScript数组的“ foreach”构造,该JavaScript数组使用此模板来呈现该数组中的项目。然后,添加一组新的输入就像将新项添加到数组一样简单。您将需要做一些工作来基于数组中项目的索引来自定义输入名称,但是所有这些客户端框架都有这样做的方法。这样做还有一个好处,就是每次您要添加新部分时都不必发出AJAX请求。