我试图将我的模型传回控制器。我已经将模型的所有字段都包含在表单中,但是一旦它返回到控制器,Employees和EmployeesInMultipleCompanies,它们都是IList类型,它就会丢失模型的两个部分。我已经验证了字段在传递到视图时存在,它们只是没有将其返回到控制器。
.cshtml
@using (Html.BeginForm("PostEmail","Import",FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>EmailViewModel</legend>
<p>
<input type="email" name="EmailAddresses" value=" " required="required" />
<span class="btn_orange"><a href="#" class="remove_field" >x</a></span>
</p>
<p>
<span class="btn_orange"><a class="add_email_button" href="#">Add Another Email</a></span>
</p>
@Html.HiddenFor(m=> Model.Employees)
@Html.HiddenFor(m=> Model.CompanyId)
@Html.HiddenFor(m=> Model.CompanyName)
@Html.HiddenFor(m=> Model.PayFrequency)
@Html.HiddenFor(m=> Model.FirstPayPeriodBeginDate)
@Html.HiddenFor(m=> Model.LastPayPeriodEndDate)
@Html.HiddenFor(m=> Model.NumberPayPeriods)
@Html.HiddenFor(m=> Model.ValidEmployees)
@Html.HiddenFor(m=> Model.InvalidEmployees)
@Html.HiddenFor(m=> Model.EmployeesInMultipleCompanies)
@Html.HiddenFor(m=> Model.TotalEmployeeCount)
<p>
<input type="submit" value="Send Email" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Cancel", "Continue", "Import")
</div>
<script type="text/javascript">
$(document).ready(function () {
$('body').on('click', '.remove_field', function () {
$(this).closest('p').remove();
});
$('.add_email_button').closest('p').click(function () {
var html = '<p><input type="email" required="required" name="EmailAddresses" /><span class="btn_orange"><a href="#" class="remove_field">x</a></span></p>';
$(html).insertBefore($(this));
});
$(body).on('click', 'submit', function() {
$('email').attr('required', true);
});
});
</script>
controller .cs
public ActionResult SendEmail(ImportViewModel model)
{
var editedEmployees = model.EmployeesInMultipleCompanies;
var importModel = TempData["ImportModel"] as ImportViewModel;
//for each employee who is in multiple companies, set user-chosen company id and the COHD related to that company
var importService = new ImportService();
importService.UpdateEmployeesInMultipleCompanies(editedEmployees, importModel.Employees);
TempData["ImportModel"] = importModel;
return this.RazorView("SendEmail", importModel);
}
[HttpPost]
public ActionResult PostEmail(ImportViewModel model)
{
IEmailer emailer = new Emailer();
emailer.SendEmail(model.EmailAddresses, model.Employees);
var employees =
model.Employees.Where(e => !string.IsNullOrWhiteSpace(e.ValidationErrorOrException)).ToList();
var emailViewModel = new EmailViewModel(employees);
return this.RazorView("Continue", emailViewModel);
}
答案 0 :(得分:2)
将其替换为以下内容:
@foreach(var i = 0; i < Model.Employees.Count; i++)
{
Html.Hiddenfor(m => m.Employees[i])
}
应该对EmployeesInMultipleCompanies
进行同样的操作答案 1 :(得分:1)
答案 2 :(得分:1)
问题不在于控制器,而在于客户端上存储值的方式。 DefaultModelBinder
非常聪明,但有时也不那么聪明。只要属性匹配,它就可以处理某些情况下的接口,复杂类型的集合以及许多其他事物。有关该行为的详细信息,请参阅此文章:http://msdn.microsoft.com/en-us/magazine/hh781022.aspx。
如果您调试控制器并检查Request.Form中的值,您将看到您的数据存储为单个值。如果模型粘合剂可以说话,他们会说:
Request.Form [&#34; EmployeesInMultipleCompanies&#34;]与我模型的EmployeesInMultipleCompanies
属性无关,因为我的模型元数据(ModelMetaDataProvider
)告诉我我应该寻找一个集合类型(IList
未知的泛型类型),这显然是一个字符串值,所以我不会绑定这个值。
要解决此问题,您必须为DefaultModelBinder提供足够的提示,以便它完成工作。这样做的一种方法是以这样的方式呈现隐藏字段,使得它们具有与它们相关联的索引器。这是模型绑定器需要以您期望的方式运行的线索。
如果您同时渲染:
@for(var i = 0; i < Model.Employees.Count; i++)
{
Html.Hiddenfor(m => m.Employees[i])
}
@for(var i = 0; i < Model.EmployeesInMultipleCompanies.Count; i++)
{
Html.Hiddenfor(m => m.EmployeesInMultipleCompanies[i])
}
然后再次调试您的调试器,您现在会在Request.Form
:
Request.Form["EmployeesInMultipleCompanies[0]"]
Request.Form["EmployeesInMultipleCompanies[1]"]
等...
现在模型绑定器可以正常工作。
或者,您可以创建一个自定义模型绑定器,它知道如何从单个输入中读取字段。
我在这里使用通用IList进行此类ModelBinding时创建了一个Gist来演示不同类型的可能结果:https://gist.github.com/xDaevax/bd35b5d88fed03709d30