@Html.HiddenFor does not work on Lists in ASP.NET

2019-01-05 01:36发布

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?

12条回答
对你真心纯属浪费
2楼-- · 2019-01-05 01:58

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.

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-05 01:59

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)
查看更多
Bombasti
4楼-- · 2019-01-05 02:03

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.

查看更多
趁早两清
5楼-- · 2019-01-05 02:10

Another option would be:

<input type="hidden" value=@(string.Join(",", Model.MyList)) />
查看更多
Lonely孤独者°
6楼-- · 2019-01-05 02:12

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.

查看更多
家丑人穷心不美
7楼-- · 2019-01-05 02:12

I started digging through the source code for HiddenFor, and I think the roadblock you're seeing is that your complex object MyList is not implicitly convertible to type string, so the framework treats your Model value as null and renders the value attribute empty.

查看更多
登录 后发表回答