@ Html.HiddenFor在ASP.NET MVC的列表中不起作用

我正在使用包含List作为属性的模型。 我使用从SQL Server获取的项来填充这个列表。 我希望列表隐藏在视图中并传递给POST操作。 后来我可能想用jQuery将更多的项目添加到这个列表,这使得数组不适合以后的扩展。 通常你会使用

@ Html.HiddenFor(model => model.MyList)

要完成这个function,但由于某种原因,POST中的List始终为空。

很简单的问题,任何人都知道为什么MVC的行为是这样的?

我刚刚遇到这个问题,并简单地通过执行以下操作来解决它:

 for(int i = 0; i < Model.ToGroups.Count; i++) { @Html.HiddenFor(model => Model.ToGroups[i]) } 

通过使用而不是一个foreach模型绑定将正常工作,并拿起列表中的所有隐藏的值。 看起来像解决这个问题最简单的方法。

HiddenFor不像DisplayFor或EditorFor。 它不会与collections,只有单一的价值观。

您可以使用MVC Futures项目中提供的Serialize HTML帮助程序将对象序列化为Hidden字段,否则您将不得不自己编写代码。 一个更好的解决方法是简单地序列化某种types的ID,并在回发中从数据库中重新获取数据。

这是一个黑客,但如果@Html.EditorFor@Html.DisplayFor为你的列表工作,如果你想确保它发送的请求,但不可见,你可以风格它使用display: none; 要隐藏它,例如:

 <div style="display: none;">@Html.EditorFor(model => model.MyList)</div> 

如何使用Newtonsoft反序列化对象到一个JSONstring,然后将其插入到您的隐藏字段,例如( Model.DataResponse.Entity.Commission是一个简单的“CommissionRange”对象的列表 ,你会在JSON中看到)

 @using (Ajax.BeginForm("Settings", "AffiliateProgram", Model.DataResponse, new AjaxOptions { UpdateTargetId = "result" })) { string commissionJson = JsonConvert.SerializeObject(Model.DataResponse.Entity.Commission); @Html.HiddenFor(data => data.DataResponse.Entity.Guid) @Html.Hidden("DataResponse_Entity_Commission", commissionJson) [Rest of my form] } 

呈现为:

 <input id="DataResponse_Entity_Commission" name="DataResponse_Entity_Commission" type="hidden" value="[{"RangeStart":0,"RangeEnd":0,"CommissionPercent":2.00000},{"RangeStart":1,"RangeEnd":2,"CommissionPercent":3.00000},{"RangeStart":2,"RangeEnd":0,"CommissionPercent":2.00000},{"RangeStart":3,"RangeEnd":2,"CommissionPercent":1.00000},{"RangeStart":15,"RangeEnd":10,"CommissionPercent":5.00000}]"> 

在我的情况下,我做一些JS的东西来编辑隐藏字段中的json之前发布回来

在我的控制器中,我再次使用Newtonsoft来反序列化:

 string jsonCommissionRange = Request.Form["DataResponse_Entity_Commission"]; List<CommissionRange> commissionRange = JsonConvert.DeserializeObject<List<CommissionRange>>(jsonCommissionRange); 

Html.HiddenFor仅为一个值devise。 您需要在创build隐藏字段之前以某种方式序列化您的列表。

例如,如果您的列表是stringtypes的,则可以将列表join逗号分隔的列表中,然后在发回控制器后拆分列表。

我刚刚发现(几个小时后,试图找出为什么模型值不会回到控制器)隐藏的应遵循EditorFor。

除非我在做别的事情,否则这是我发现的。 我不会再犯这个错误了。

在包含另一个类的列表的Model的上下文中。

这不会工作:

  @{ for (int i = 0; i < Model.Categories.Count; i++) { <tr> <td> @Html.HiddenFor(modelItem => Model.Categories[i].Id) @Html.HiddenFor(modelItem => Model.Categories[i].ProductCategoryId) @Html.HiddenFor(modelItem => Model.Categories[i].CategoryName) @Html.DisplayFor(modelItem => Model.Categories[i].CategoryName) </td> <td> @Html.HiddenFor(modelItem => Model.Categories[i].DailyPurchaseLimit) @Html.EditorFor(modelItem => Model.Categories[i].DailyPurchaseLimit) @Html.ValidationMessageFor(modelItem => Model.Categories[i].DailyPurchaseLimit) </td> <td style="text-align: center"> @Html.HiddenFor(modelItem => Model.Categories[i].IsSelected) @Html.EditorFor(modelItem => Model.Categories[i].IsSelected) </td> </tr> } } 

哪里这样……

  for (int i = 0; i < Model.Categories.Count; i++) { <tr> <td> @Html.HiddenFor(modelItem => Model.Categories[i].Id) @Html.HiddenFor(modelItem => Model.Categories[i].ProductCategoryId) @Html.HiddenFor(modelItem => Model.Categories[i].CategoryName) @Html.DisplayFor(modelItem => Model.Categories[i].CategoryName) </td> <td> @Html.EditorFor(modelItem => Model.Categories[i].DailyPurchaseLimit) @Html.HiddenFor(modelItem => Model.Categories[i].DailyPurchaseLimit) @Html.ValidationMessageFor(modelItem => Model.Categories[i].DailyPurchaseLimit) </td> <td style="text-align: center"> @Html.EditorFor(modelItem => Model.Categories[i].IsSelected) @Html.HiddenFor(modelItem => Model.Categories[i].IsSelected) </td> </tr> } 

你可以看看这个解决scheme 。

在EditorTemplate中只放置HiddenFor。

并在你的观点把这个: @Html.EditorFor(model => model.MyList)

它应该工作。

我开始深入研究HiddenFor的源代码,我认为你看到的障碍是你的复杂对象MyList不能隐式转换为stringtypes,所以框架将你的Model值视为null ,并将value属性赋值为空。

解决这个问题的另一种方法是给列表中的每个对象一个ID,然后使用@Html.DropDownListFor(model => model.IDs)并填充一个包含ID的数组。

也许晚了,但我创build的集合隐藏字段的扩展方法(简单的数据types的项目):

所以这里是:

 /// <summary> /// Returns an HTML hidden input element for each item in the object's property (collection) that is represented by the specified expression. /// </summary> public static IHtmlString HiddenForCollection<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) where TProperty : ICollection { var model = html.ViewData.Model; var property = model != null ? expression.Compile().Invoke(model) : default(TProperty); var result = new StringBuilder(); if (property != null && property.Count > 0) { for(int i = 0; i < property.Count; i++) { var modelExp = expression.Parameters.First(); var propertyExp = expression.Body; var itemExp = Expression.ArrayIndex(propertyExp, Expression.Constant(i)); var itemExpression = Expression.Lambda<Func<TModel, object>>(itemExp, modelExp); result.AppendLine(html.HiddenFor(itemExpression).ToString()); } } return new MvcHtmlString(result.ToString()); } 

用法如下简单:

 @Html.HiddenForCollection(m => m.MyList)