【问题标题】:ASP.NET Core - Bind IEnumerable<T> to a ViewModel field on POSTASP.NET Core - 将 IEnumerable<T> 绑定到 POST 上的 ViewModel 字段
【发布时间】:2019-02-06 14:08:23
【问题描述】:

我有一个用于将团队注册到比赛的网络应用程序,每个团队都可以在其中选择他们将用于他们的项目的许多技术。这些技术保存在 Label 类中。

我正在使用视图模型将信息从表单绑定到操作。 但是,当我尝试提交表单时,它会占用除技术列表之外的所有其他字段。

Label.cs

public class Label
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public string ColorPalette { get; set; }
}

CreateTeamViewModel.cs

public class CreateTeamViewModel
{
    [Required]
    public string TeamName { get; set; }

    public string ProjectName { get; set; }

    public string ProjectDescription { get; set; }

    [Required]
    public string RepositoryLink { get; set; }

    public List<Label> Labels = new List<Label>();
}

TeamsController.cs

public class TeamsController
{
    private readonly ApplicationDbContext context;

    public IActionResult Create()
    {
        ViewData["Labels"] = this.context.Labels.ToList();
        return View();
    }

    [HttpPost]
    public IActionResult Create(CreateTeamViewModel team)
    {
        List<Label> labels = team.Labels;
        int count = labels.Count; // count = 0
        return LocalRedirect("/");
    }
}

Create.cshtml(复选框列表)

@model Competition.Data.ViewModels.CreateTeamViewModel

@{ 
    List<Label> labels = ViewData["Labels"] as List<Label>;
}

<form asp-action="Create">
    <div class="form-check">
        @for(int i = 0; i < labels.Count; i++)
        {
            <input asp-for="@Model.Labels[i].IsSelected" type="checkbox" />
            <label asp-for="@Model.Labels[i].Name">
                <span class="badge badge-@labels[i].ColorPalette">@labels[i].Name</span>
            </label>
            <input asp-for="@Model.Labels[i].Name" type="hidden" value="@labels[i].Name" />
            <input asp-for="@Model.Labels[i].ColorPalette" type="hidden" value="@labels[i].ColorPalette" />
        }
    </div>
    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-default" />
    </div>
</form>

【问题讨论】:

    标签: c# razor asp.net-core


    【解决方案1】:

    您需要在视图模型上绑定到 int 列表而不是 Label 列表。然后,您需要使用该选定 ID 列表来填充您要持久化的 Team 实体上的标签列表:

    public class CreateTeamViewModel
    {
        [Required]
        public string TeamName { get; set; }
    
        public string ProjectName { get; set; }
    
        public string ProjectDescription { get; set; }
    
        [Required]
        public string RepositoryLink { get; set; }
    
        public List<int> SelectedLabels { get; set; } = new List<int>();
    }
    

    然后,您需要修改表单以将复选框绑定到此列表:

    @foreach (var label in labels)
    {
        <input asp-for="SelectedLabels" id="Label@(label.Id)" value="@label.Id" type="checkbox" />
        <label id="Label@(label.Id)">
            <span class="badge badge-@label.ColorPalette">@label.Name</span>
        </label>
    }
    

    请注意,我删除了隐藏的输入。您应该永远发布用户不能修改的任何内容,因为即使是隐藏的输入也可能被篡改。

    发布后,您将在服务器端获得用户选择的标签 ID 列表。只需从数据库中查询相关标签,然后将其分配给您正在创建的团队:

    team.Labels = await _context.Set<Label>().Where(x => model.SelectedLabels.Contains(x.Id)).ToListAsync();
    

    【讨论】:

    • 工作就像一个魅力,虽然我不得不用 name 标签更改 asp-for 标签。感谢您的快速回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多