模型内的列表项在发布时始终为空 - Asp.net MVC

Vig*_*dan 3 c# asp.net razor asp.net-mvc-4

我正在尝试发布包含List<>项目的模型,如下所示:

public class AddSubscriptionPlanModel
{
    public AddSubscriptionPlanModel()
    {
        AllFeatures = new List<Feature>();
    }
    public int Id { get; set; }
    public int SubscriptionPlanId { get; set; }
    public int SubscriptionId { get; set; }
    public string Name { get; set; }
    public bool IsActive { get; set; }
    [Display(Name = "No Of Users")]
    public int? NoOfUsers { get; set; }
    [Display(Name = "Duration Type")]
    public DurationType DurationType { get; set; }
    public int Duration { get; set; }
    public decimal Amount { get; set; }
    public int SubscriptionPlanTrailId { get; set; }
    public int FeatureId { get; set; }
    public DateTime CreatedDateUtc { get; set; }
    public DateTime LastUpdatedUtc { get; set; }
    public int CreatedBy { get; set; }
    public int LastUpdatedBy { get; set; }    
    public List<Feature> AllFeatures { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我正在填充 get 方法的所有必填字段并从数据库提供列表

public ActionResult Mapping(int id)
{        
    var features = FeatureManager.GetAllFeatures();
    var model = new Ejyle.DevAccelerate.Web.App.Models.SubscriptionPlan.AddSubscriptionPlanModel();

    model.AllFeatures = features;
    model.Id = id;
    model.SubscriptionId = id;
    model.NoOfUsers = 20;
    model.SubscriptionPlanId = 1;
    model.SubscriptionPlanTrailId = 1;
    model.Amount = 1000;
    model.CreatedBy = 1;
    model.LastUpdatedBy = 1;
    model.FeatureId = 1;
    model.Duration = 20;

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

我的视图代码如下所示:

@using (Html.BeginForm("Mapping", "SubscriptionPlans", FormMethod.Post))
{
    @Html.HiddenFor(model => model.Id)
    @Html.HiddenFor(model => model.Amount)
    @Html.HiddenFor(model => model.Duration)
    @Html.HiddenFor(model => model.FeatureId)
    @Html.HiddenFor(model => model.CreatedBy)
    @Html.HiddenFor(model => model.LastUpdatedBy)
    @Html.HiddenFor(model => model.NoOfUsers)
    @Html.HiddenFor(model => model.SubscriptionId)
    @Html.HiddenFor(model => model.SubscriptionPlanId)
    @Html.HiddenFor(model => model.SubscriptionPlanTrailId)
    @Html.HiddenFor(model => model.AllFeatures)
    <table class="table table-striped">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Name)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.IsActive)
                </th>
            </tr>
        </thead>
        <tbody>
            @for (int i=0; i < Model.AllFeatures.Count; i++)
            {
                <tr>
                    @Html.HiddenFor(model => model.AllFeatures[i].Id)
                    @Html.HiddenFor(model => model.AllFeatures[i].Name)
                    @Html.HiddenFor(model => model.AllFeatures[i].IsActive)
                    <td>
                        @Html.TextBoxFor(model => model.AllFeatures[i].Id)
                    </td>
                    <td>
                        @Html.TextBoxFor(model => model.AllFeatures[i].Name)
                    </td>
                    <td>
                        @Html.EditorFor(model => model.AllFeatures[i].IsActive)
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <input type="submit" class="btn btn-success" value="Submit" name="Submit"/>
}
Run Code Online (Sandbox Code Playgroud)

在视图中,列表项正确呈现,甚至我也可以编辑这些字段。但在发布时,除了AllFeatures列表项属性始终显示 count = 0
之外,所有属性都具有值。

编辑 1:这是我的视图在渲染功能时的样子

在此输入图像描述

编辑2:

方法签名发布到:

[HttpPost]
public ActionResult Mapping(AddSubscriptionPlanModel model)
{       
}
Run Code Online (Sandbox Code Playgroud)

Cod*_*shi 8

但在发布时,除了 AllFeatures 列表项属性始终显示 count = 0 之外,所有属性都具有值。

AllFeatures是一个通用列表Feature。当你这样做时:

@Html.HiddenFor(model => model.AllFeatures) 
Run Code Online (Sandbox Code Playgroud)

Razor 视图引擎将呈现以下内容:

<input id="AllFeatures" 
       name="AllFeatures" 
       type="hidden" 
       value="System.Collections.Generic.List`1[Namespace.Feature]">
       <!--Where Namespace is the Namespace where Feature is defined. -->
Run Code Online (Sandbox Code Playgroud)

换句话说,HiddenFor调用ToString()项目上的 并将其放入input标签的value属性中。

POST 后会发生什么

当您发布表单时,它DefaultModelBinder正在寻找一个名为AllFeatures但类型的属性string,以便它可以将其分配给它:

System.Collections.Generic.List`1[Namespace.Feature]
Run Code Online (Sandbox Code Playgroud)

它找不到一个,因为您的模型没有AllFeaturesof type string,因此它只是忽略它并绑定所有其他属性。

AllFeatures 列表项属性始终显示 count = 0。

是的,它会的,这不是AllFeatures您发布的列表,而是来自构造函数的列表,它显然是一个计数为 0 的空列表:

public AddSubscriptionPlanModel()
{
    AllFeatures = new List<Feature>();
}
Run Code Online (Sandbox Code Playgroud)

我不确定为什么您将所有功能发送到客户端(浏览器),然后需要将其发布回服务器。

解决方案

要解决此问题,只需删除此行:

@Html.HiddenFor(model => model.AllFeatures)
Run Code Online (Sandbox Code Playgroud)

现在,在绑定过程中不会造成任何混乱,MVC 会将循环中的项目绑定到属性AllFeatures

事实上,据我从你的问题中可以看出,你真正需要的唯一代码是这个(如果你出于其他原因需要隐藏字段,我可能是错的。但是如果你只是想让用户编辑 AllFeatures,你不需要任何隐藏字段):

@for (int i = 0; i < Model.AllFeatures.Count; i++)
{
    <tr>
        <td>
            @Html.TextBoxFor(model => model.AllFeatures[i].Id)
        </td>
        <td>
            @Html.TextBoxFor(model => model.AllFeatures[i].Name)
        </td>
        <td>
            @Html.EditorFor(model => model.AllFeatures[i].IsActive)
        </td>
    </tr>
}
Run Code Online (Sandbox Code Playgroud)