我是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.
为了让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方法中只有一个参数,因此应该没问题.