mvc 5,模型是列表,提交的模型是空的

mvc 5, model is List, submited model is null

我需要提交技能列表。当我尝试这样做时,提交的模型为空。但在 Fidler 中,我看到数据已发送。

public class MvcSkill
{
    [HiddenInput(DisplayValue = false)]
    public int Id { get; set; }

    [Display(Name = "Category Name")]
    [StringLength(128, ErrorMessage = "Max length - {0} symbols")]
    [Required(ErrorMessage = "Please enter your last name")]
    public string Name { get; set; }

    public int Level { get; set; }

    [Required(ErrorMessage ="Choose skill category")]
    public string CategoryName { get; set; }
}

每个技能的部分视图(技能级别的奇怪输入是 bootstrap-star-rating:

@using MvcApp.Infrastructure;
@model MvcApp.ViewModels.MvcSkill

<tr>
    <td>
        @Html.HiddenFor(x => x.Id)
    </td>
    <td>
        @Html.HiddenFor(x => x.Name)
        @Html.DisplayFor(x => x.Name)
    </td>
    <td>
        @Html.HiddenFor(x => x.CategoryName)
        @Html.DisplayFor(x => x.CategoryName)
    </td>
    <td>
        <input for="Level" id="@Model.Id" value="@Model.Level" name="Level" type="number" class="rating-loading" data-size="xs" data-min="0" data-max="5" data-step="1" data-show-clear="false">
    </td>

    @{
        var identity = (CustomIdentity)User.Identity;

        if (identity.Roles.FirstOrDefault(r => r == "Administrator") != null)
        {
            <td>
                @Html.RouteLink("Edit", new { controller = "Administrator", action = "EditSkill", id = Model.Id })
            </td>
            <td>
                @Html.RouteLink("Remove", new { controller = "Administrator", action = "RemoveSkill", id = Model.Id })
            </td>
        }
    }
</tr>

查看技能列表:

@model IList<MvcApp.ViewModels.MvcSkill>

@{
    ViewBag.Title = "Skills";
}
@using (Html.BeginForm("Index","Skill", Model))
{
    <table>
        @foreach (var s in Model)
        {
            @Html.Partial("_Skill", s)
        }
    </table>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input id="submit" type="submit" value="Update" class="btn btn-default" />
        </div>
    </div>
}

@section scripts{
    <link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet">
    <link href="~/Content/star-rating.css" media="all" rel="stylesheet" type="text/css" />
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.js"></script>
    <script src="~/Scripts/star-rating.js" type="text/javascript"></script>
    @foreach (var item in Model)
    {
        string id = item.Id.ToString();
        <script>
            $(document).on('ready', function () {
                $('#@id').rating({
                    step: 1,
                    defaultCaption: 'Unknown',
                    starCaptions: { 0: 'Unknown', 1: 'Beginner', 2: 'Elementary', 3: 'Intermediate', 4: 'Advanced', 5: 'Profi' },
                    starCaptionClasses: function (val) { return 'text-success'; }
                }).on('rating.change', function (event, value, caption) {
                    Model.Skills.FirstOrDefault(s => s.Key.Id.ToString() == id).Value = value;
                });
            });            
        </script>
    }
}

和控制器方法:

[HttpPost]
        public ActionResult Index(List<MvcSkill> skillModel)
        {
            //Do something...

            return View();
        }

Fidler 文本: Id=1&Name=c%2B%2B&CategoryName=Programing&Level=5&Id=3&Name=PHP&CategoryName=Programing&Level=3&Id=6&Name=JAVA&CategoryName=Programing&Level=3&Id=7&Name=Name&CategoryName=.Net+Frameworks&Level=5

您必须手动添加 indexes 以便 MVC 框架可以成功绑定数据。类似于:

@using (Html.BeginForm("Index","Skill", Model))
{
    <table>
        @for (int i = 0; i < Model.Length; i++)
        {
            <tr>
                <td>
                    @Html.Hidden("[" + i + "].Id");
                </td>               
                <td>
                    @Html.DisplayFor(m => Model.ElementAt(i).Name)
                    @Html.Hidden("[" + i + "].Name");
                </td>
                <td>
                    @Html.DisplayFor(m => Model.ElementAt(i).CategoryName)
                    @Html.Hidden("[" + i + "].CategoryName");
                </td>
            </tr>
        }
    </table>
}

或者,如评论中所述,您可以使用 BeginCollectionItem(我个人使用)。 BeginCollectionItem 所做的是,通常它会添加 GUIDs 作为您的索引。可以找到源代码 here and you can get familiar with it here.