@Html.HiddenFor 不适用于 ASP.NET MVC 中的列表
我正在使用包含列表作为属性的模型。我用从 SQL Server 获取的项目填充此列表。我希望列表隐藏在视图中并传递给 POST 操作。稍后我可能想使用 jQuery 将更多项目添加到此列表中,这使得数组不适合稍后扩展。通常您会使用它
@Html.HiddenFor(model => model.MyList)
来完成此功能,但由于某种原因,POST 中的列表始终为空。
很简单的问题,有人知道为什么 MVC 会这样吗?
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
@Html.HiddenFor(model => model.MyList)
to accomplish this functionality, but for some reason the List in POST is always null.
Very simple question, anyone know why MVC behaves like this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
我刚刚遇到这个问题,并通过执行以下操作简单地解决了它:
通过使用
for
而不是foreach
模型绑定将正常工作并拾取所有您在列表中的隐藏值。似乎是解决这个问题的最简单的方法。I've just come across this issue and solved it simply by doing the following:
By using a
for
instead of aforeach
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.HiddenFor 与 DisplayFor 或 EditorFor 不同。它不适用于集合,仅适用于单个值。
您可以使用 MVC Futures 项目中提供的序列化 HTML 帮助程序将对象序列化到隐藏字段,否则您必须自己编写代码。更好的解决方案是简单地序列化某种 ID,并在回发时从数据库重新获取数据。
HiddenFor is not like a DisplayFor or EditorFor. It won't work with collections, only single values.
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.
这有点像黑客,但如果
@Html.EditorFor
或@Html.DisplayFor
适用于您的列表,如果您想确保它在发布请求中发送,但不可见,您可以将其样式设置为使用display: none;
来隐藏它,例如:It's a bit of a hack, but if
@Html.EditorFor
or@Html.DisplayFor
work 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 usingdisplay: none;
to hide it instead, e.g:怎么样使用 Newtonsoft 将对象反序列化为 json 字符串,然后将其插入到您的隐藏字段中,例如
(Model.DataResponse.Entity.Commission 是简单 "CommissionRange" 对象的列表,如您在 JSON 中看到的那样)
呈现为:
就我而言,我在回发之前做了一些 JS 操作来编辑隐藏字段中的 json,
然后在我的控制器中再次使用 Newtonsoft 进行反序列化:
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.Commission is a List of simple "CommissionRange" objects as you'll see in the JSON)
Renders as:
In my case I do some JS stuff to edit the json in the hidden field before posting back
In my controller I then use Newtonsoft again to deserialize:
Html.HiddenFor
仅为一个值而设计。在创建隐藏字段之前,您需要以某种方式序列化列表。例如,如果您的列表是字符串类型,您可以将列表连接到逗号分隔的列表中,然后在发回控制器后拆分列表。
Html.HiddenFor
is designed for only one value. You will need to serialize your list in some way before creating the hidden field.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.
我刚刚发现(经过几个小时试图弄清楚为什么模型值没有返回到控制器)隐藏的 for 应该遵循 EditorFor。
除非我做错了什么,这就是我发现的。我不会再犯同样的错误了。
在包含另一个类的列表的模型的上下文中。
这行不通:
这会行不通……
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.
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:
Where as this WILL......
我开始深入研究
HiddenFor
的源代码,我认为您看到的障碍是您的复杂对象MyList
不能隐式转换为string< 类型/code>,因此框架将您的
Model
值视为null
并将value
属性呈现为空。I started digging through the source code for
HiddenFor
, and I think the roadblock you're seeing is that your complex objectMyList
is not implicitly convertible to typestring
, so the framework treats yourModel
value asnull
and renders thevalue
attribute empty.您可以查看这个解决方案。
仅将 HiddenFor 放入 EditorTemplate 中。
在你的视图中输入:
@Html.EditorFor(model => model.MyList)
它应该可以工作。
You can take a look on this solution.
Put only HiddenFor inside the EditorTemplate.
And in your View put this:
@Html.EditorFor(model => model.MyList)
It should works.
面临同样的问题。如果没有 for 循环,它只发布列表的第一个元素。迭代for循环后,它可以保留完整列表并成功发布。
Faced the same issue. Without for loop, it only posted the first element of the list. After iterating through for loop, it can keep full list and post successfully.
另一种选择是:
Another option would be:
使用
foreach
循环代替for
循环可能是一个稍微简洁的解决方案。The
foreach
loop instead of afor
loop might be a slightly cleaner solution.解决此问题的另一种可能方法是为列表中的每个对象提供一个 ID,然后使用 @Html.DropDownListFor(model => model.IDs) 并填充一个保存 ID 的数组。
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.也许晚了,但我为集合中的隐藏字段创建了扩展方法(使用简单的数据类型项):
所以这里是:
用法很简单:
maybe late, but i created extension method for hidden fields from collection (with simple data type items):
So here it is:
Usage is as simple as:
添加到 这个答案,我有一个具有各种属性的模型,其中一些是 IEnumerables。我所做的是将其序列化到视图中的变量中:
然后,将该字符串放入隐藏元素中(因为 HiddenFor 用于模型中的单个值),如下所示:
最后,在控制器中,我可以反序列化它
Adding to this answer, I had a Model with various properties, some of which were IEnumerables. What I did was to serialize it in a variable in the view with:
And then, put that string into a Hidden element (since HiddenFor is intended for a single value from a Model) like this:
And finally, in the controller, I could deserialize it with