C# @Html.HiddenFor 不适用于 ASP.NET MVC 中的列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9385286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@Html.HiddenFor does not work on Lists in ASP.NET MVC
提问by Anton Smith
I'm using a model that contains a List as a property. I'm populating this list with items i grab from SQL Server. I want the List to be hidden in the view and passed to the POST action. Later on i may want to add more items to this List with jQuery which makes an array unsuitable for expansion later on. Normally you would use
我正在使用一个包含 List 作为属性的模型。我正在使用从 SQL Server 中获取的项目填充此列表。我希望列表隐藏在视图中并传递给 POST 操作。稍后我可能想使用 jQuery 向此列表添加更多项目,这使得数组不适合稍后扩展。通常你会使用
@Html.HiddenFor(model => model.MyList)
to accomplish this functionality, but for some reason the List in POST is always null.
来完成此功能,但由于某种原因,POST 中的列表始终为空。
Very simple question, anyone know why MVC behaves like this?
很简单的问题,有人知道为什么 MVC 会这样吗?
采纳答案by Daniel Mackay
I've just come across this issue and solved it simply by doing the following:
我刚刚遇到了这个问题,并通过执行以下操作解决了它:
@for(int i = 0; i < Model.ToGroups.Length; i++)
{
@Html.HiddenFor(model => Model.ToGroups[i])
}
By using a for instead of a foreach the model binding will work correctly and pick up all of your hidden values in the list. Seems like the simplest way to solve this problem.
通过使用 for 而不是 foreach,模型绑定将正常工作并获取列表中的所有隐藏值。似乎是解决这个问题的最简单方法。
回答by Kyle Trauberman
Html.HiddenForis designed for only one value. You will need to serialize your list in some way before creating the hidden field.
Html.HiddenFor仅为一个值而设计。在创建隐藏字段之前,您需要以某种方式序列化您的列表。
For example, if your list is of type string, you could join the list into a comma separated list, then split the list after post back in your controller.
例如,如果您的列表是字符串类型,您可以将列表加入一个逗号分隔的列表中,然后在您的控制器中回发后拆分列表。
回答by Erik Funkenbusch
HiddenFor is not like a DisplayFor or EditorFor. It won't work with collections, only single values.
HiddenFor 不像 DisplayFor 或 EditorFor。它不适用于集合,只能使用单个值。
You can use the Serialize HTML helper available in the MVC Futures project to serialize an object to a Hidden field, or you will have to write the code yourself. A better solution is to simply serialize an ID of some sort and re-get the data from the database on postback.
您可以使用 MVC Futures 项目中提供的 Serialize HTML helper 将对象序列化为 Hidden 字段,或者您必须自己编写代码。更好的解决方案是简单地序列化某种 ID 并在回发时从数据库中重新获取数据。
回答by C???
I started digging through the source code for HiddenFor, and I think the roadblock you're seeing is that your complex object MyListis not implicitly convertible to type string, so the framework treats your Modelvalue as nulland renders the valueattribute empty.
我开始挖掘 的源代码HiddenFor,我认为您看到的障碍是您的复杂对象MyList不能隐式转换为 type string,因此框架将您的Model值视为null并将value属性呈现为空。
回答by Wilfart Benjamin
回答by Mark Rhodes
It's a bit of a hack, but if @Html.EditorForor @Html.DisplayForwork for your list, if you want to make sure it's sent on the post request but not visible, you could just style it to using display: none;to hide it instead, e.g:
这有点麻烦,但是如果@Html.EditorFor或@Html.DisplayFor适用于您的列表,如果您想确保它在发布请求中发送但不可见,您可以将其设置为display: none;用于隐藏它,例如:
<div style="display: none;">@Html.EditorFor(model => model.MyList)</div>
回答by deckeresq
Another possible way to fix this would be to give each object in your List an ID, then use @Html.DropDownListFor(model => model.IDs)and populate an array which holds the IDs.
解决此问题的另一种可能方法是为列表中的每个对象提供一个 ID,然后使用@Html.DropDownListFor(model => model.IDs)并填充一个包含 ID 的数组。
回答by AntDC
I've just found out (after a couple of hours of trying to figure out why model values weren't going back to the controller) that hidden for should follow the EditorFor.
我刚刚发现(经过几个小时试图弄清楚为什么模型值没有回到控制器之后)隐藏的应该遵循 EditorFor。
Unless I am doing something else wrong this is what I found. I will not make the mistake again.
除非我做错了什么,这就是我发现的。我不会再犯这个错误了。
In the context of a Model that contains a list of another class.
在包含另一个类列表的模型的上下文中。
This will NOT work:
这将不起作用:
@{
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>
}
}
Where as this WILL......
这将在哪里......
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>
}
回答by Adam Hey
What about using Newtonsoft to deserialize the object into a json string and then insert that into your Hidden field e.g. (Model.DataResponse.Entity.Commissionis a Listof simple "CommissionRange"objects as you'll see in the JSON)
如何使用 Newtonsoft 将对象反序列化为 json 字符串,然后将其插入到您的隐藏字段中,例如(Model.DataResponse.Entity.Commission是您将在 JSON 中看到的简单“CommissionRange”对象列表)
@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]
}
Renders as:
呈现为:
<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}]">
In my case I do some JS stuff to edit the json in the hidden field before posting back
在我的情况下,我在回发之前做了一些 JS 的东西来编辑隐藏字段中的 json
In my controller I then use Newtonsoft again to deserialize:
在我的控制器中,我再次使用 Newtonsoft 反序列化:
string jsonCommissionRange = Request.Form["DataResponse_Entity_Commission"];
List<CommissionRange> commissionRange = JsonConvert.DeserializeObject<List<CommissionRange>>(jsonCommissionRange);
回答by Gh61
maybe late, but i created extension method for hidden fields from collection (with simple data type items):
也许晚了,但我为集合中的隐藏字段创建了扩展方法(使用简单的数据类型项):
So here it is:
所以这里是:
/// <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());
}
Usage is as simple as:
用法很简单:
@Html.HiddenForCollection(m => m.MyList)

