将未知数量的Input元素绑定到MVC5中的模型

L1g*_*ira 2 c# asp.net-mvc-5

我是MVC5和C#的新手,我正在努力实现一些我不完全理解的东西.

我有一个像这样的团队模型:

public class Team
{
    [Key]
    public Guid ID { get; set; }
    public string TeamName { get; set; }
    public string Coach { get; set; }
    public string Conference { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我也有像这样的玩家模型:

public class Player
{
    [Key]
    public Guid Id { get; set; }
    [ForeignKey("Teams")]
    public Guid TeamId { get; set; }
    public string Name { get; set; }
    public virtual Team Teams { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

查看模型是

public class TeamViewModel
{
    public string TeamName { get; set; }
    public string Coach { get; set; }
    public string Conference { get; set; }
    public List<Player> Players { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

通过这种结构,您可以为每个团队添加无限数量的玩家.因此,我有一个具有少量属性的Teams表和一个包含玩家名称以及玩家TeamId的Player表,以便我们知道他们属于哪个团队.

当我创建团队时,我的问题出现了.我有这样的Create Controller:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(TeamViewModel model)
{
    if (ModelState.IsValid)
    {
        var team = new Team { TeamName = model.TeamName, Coach = model.Coach, Conference = model.Conference, Player = model.Player };
        db.Teams.Add(team);
        var result = await db.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    return View();
}
Run Code Online (Sandbox Code Playgroud)

我的观点如下:

@model SoccerTeams.Models.ViewModels.TeamViewModel
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Team</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.TeamName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.TeamName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.TeamName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Coach, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Coach, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Coach, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Conference, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Conference, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Conference, "", new { @class = "text-danger" })
            </div>
        </div>
        @if (@Model != null)
        {
            foreach (var p in Model.Player)
            {
                <div class="form-group">
                    @Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
                    <div class="col-md-10">
                        @Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
                    </div>
                </div>
            }
        }
        else
        {
            <div class="form-group">
                @Html.Raw("<label class=\"control-label col-md-2\">Player</label>")
                <div class="col-md-10">
                    @Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
                </div>
            </div>
        }
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,View假设能够将input元素转换为列表并将其传递给我的ViewModel.但是,我的ViewModel始终为null.

我错过了什么,我将如何使这项工作?

PS我明白我可以使用Html.EditorFor,但我无法使其工作,所以我只是将其打印为Html,因为我需要首先解决我的其他问题.

编辑

我已将视图更改为具有以下代码

<div class="form-group">
                @Html.Raw("<label class=\"control-label col-md-2\">Player</label>")
                <div class="col-md-10">
                    @Html.Raw("<input class=\"form-control text-box single-line\" name=\"model.Players[0].Name\" type-\"text\"")
                </div>
            </div>
Run Code Online (Sandbox Code Playgroud)

因此,模型现在可以正确填充Players Array,但是所有其他值现在都变为null.如果我删除了输入元素,则会填充值,但是player数组再次为null,因为没有表单字段.你知道什么可能是罪魁祸首吗?

在TeamViewModel中,我还将Player重命名为Players.

gyo*_*fov 5

为了让MVC将表单数据绑定到Action方法的参数,它们的名称应该匹配.

假设您的ViewModel具有List<Player> Players代码属性应该是:

在你的情况下:

foreach (var p in Model.Player)
            {
                <div class="form-group">
                    @Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
                    <div class="col-md-10">
                        @Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
                    </div>
                </div>
            }
Run Code Online (Sandbox Code Playgroud)

应该:

for (int i = 0; i < Model.Player.Length; i++)
            {
                <div class="form-group">
                    @Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
                    <div class="col-md-10">
                        @Html.Raw("<input class=\"form-control text-box single-line\" name=\"model.Player[" + i + "].Name\" type-\"text\"")
                    </div>
                </div>
            }
Run Code Online (Sandbox Code Playgroud)

因为这是您提供的参数的名称:

Create(TeamViewModel model)
Run Code Online (Sandbox Code Playgroud)

另外要小心,因为索引不应该被破坏,这意味着它们应该是0,1,2 ......等而不会跳过一个数字.

我们在属性中读取的方式是查找parameterName [index] .PropertyName.索引必须从零开始且不间断.

注:你可以阅读更多关于斯科特Hanselman的结合后的集合- 在这里


最后我建议如果你有一个属性列表的属性 - 在你的案例列表中Player使用复数形式的属性名称 - Players.

编辑

尝试删除"模型".在名字的前面.使它像这样的"玩家[0] .Name".由于您在Create Action方法中只有一个参数,因此应该没问题.