C# @Html.HiddenFor不适用于ASP.NET MVC中的列表

C# @Html.HiddenFor不适用于ASP.NET MVC中的列表,c#,asp.net,asp.net-mvc-3,hidden-field,C#,Asp.net,Asp.net Mvc 3,Hidden Field,我使用的模型包含一个列表作为属性。我正在用从SQL Server获取的项目填充此列表。我希望列表隐藏在视图中并传递给POST操作。稍后,我可能想使用jQuery将更多项添加到此列表中,这使得数组不适合以后的扩展。通常你会使用 @Html.HiddenFor(model => model.MyList) 要完成此功能,但由于某些原因,POST中的列表始终为空 非常简单的问题,有人知道MVC为什么会这样吗?Html.HiddenFor只为一个值设计。在创建隐藏字段之前,需要以某种方式序列化列

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

@Html.HiddenFor(model => model.MyList)
要完成此功能,但由于某些原因,POST中的列表始终为空


非常简单的问题,有人知道MVC为什么会这样吗?

Html.HiddenFor
只为一个值设计。在创建隐藏字段之前,需要以某种方式序列化列表


例如,如果列表的类型为字符串,则可以将列表合并为逗号分隔的列表,然后在控制器中发回后拆分列表。

HiddenFor与DisplayFor或EditorFor不同。它不适用于集合,只适用于单个值


您可以使用MVC Futures项目中提供的Serialize HTML帮助程序将对象序列化为隐藏字段,或者您必须自己编写代码。更好的解决方案是简单地序列化某种类型的ID,并在回发时从数据库中重新获取数据。

我开始挖掘
HiddenFor
的源代码,我认为您看到的障碍是您的复杂对象
MyList
不能隐式转换为类型
string
,因此,框架将您的
模型
值视为
null
,并将
属性呈现为空。

您可以查看一下

在EditorTemplate中仅放置HiddenFor

在您的视图中,可以这样写:
@Html.EditorFor(model=>model.MyList)


它应该可以工作。

这是一个小技巧,但是如果
@Html.EditorFor
@Html.DisplayFor
对您的列表有效,如果您想确保它在post请求时发送但不可见,您可以使用
display:none将其隐藏,例如:

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

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

我刚刚遇到了这个问题,只需执行以下操作即可解决此问题:

@for(int i = 0; i < Model.ToGroups.Length; i++)
{
    @Html.HiddenFor(model => Model.ToGroups[i])
}
@for(int i=0;imodel.ToGroups[i])
}
通过使用for而不是foreach,模型绑定将正常工作并拾取列表中的所有隐藏值。这似乎是解决此问题的最简单方法。

我刚刚发现(在花了几个小时试图弄清楚为什么模型值没有返回控制器后),隐藏的应该遵循EditorFor

除非我做错了什么,这就是我发现的。我不会再犯错误了

在包含另一个类列表的模型上下文中

这是行不通的:

        @{
            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>
            }
        }
@{
对于(int i=0;iModel.Categories[i].Id)
@Html.HiddenFor(modelItem=>Model.Categories[i].ProductCategoryId)
@Html.HiddenFor(modeleItem=>Model.Categories[i].CategoryName)
@Html.DisplayFor(modelItem=>Model.Categories[i].CategoryName)
@Html.HiddenFor(modeleItem=>Model.Categories[i].DailyPurchaseLimit)
@Html.EditorFor(modeleItem=>Model.Categories[i].DailyPurchaseLimit)
@Html.ValidationMessageFor(modelItem=>Model.Categories[i].DailyPurchaseLimit)
@Html.HiddenFor(modeleItem=>Model.Categories[i].IsSelected)
@EditorFor(modelItem=>Model.Categories[i].IsSelected)
}
}
尽管如此

            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>
            }
for(int i=0;iModel.Categories[i].Id)
@Html.HiddenFor(modelItem=>Model.Categories[i].ProductCategoryId)
@Html.HiddenFor(modeleItem=>Model.Categories[i].CategoryName)
@Html.DisplayFor(modelItem=>Model.Categories[i].CategoryName)
@Html.EditorFor(modeleItem=>Model.Categories[i].DailyPurchaseLimit)
@Html.HiddenFor(modeleItem=>Model.Categories[i].DailyPurchaseLimit)
@Html.ValidationMessageFor(modelItem=>Model.Categories[i].DailyPurchaseLimit)
@EditorFor(modelItem=>Model.Categories[i].IsSelected)
@Html.HiddenFor(modeleItem=>Model.Categories[i].IsSelected)
}

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

呈现为:

<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);
str
string jsonCommissionRange = Request.Form["DataResponse_Entity_Commission"];
List<CommissionRange> commissionRange = JsonConvert.DeserializeObject<List<CommissionRange>>(jsonCommissionRange);
/// <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)
 @if (Model.MyList!= null)
    {
    for (int i = 0; i < Model.MyList.Count; i++)
      {
        @Html.HiddenFor(x => x.MyList[i])
      }
    }
<input type="hidden" value=@(string.Join(",", Model.MyList)) />
@foreach(var item in Model.ToGroups)
{
    @Html.HiddenFor(model => item)
}