C# Razor代码在循环通过复选框列表时产生意外结果

C# Razor代码在循环通过复选框列表时产生意外结果,c#,razor,asp.net-core-mvc,asp.net-core-2.2,C#,Razor,Asp.net Core Mvc,Asp.net Core 2.2,此代码可能有什么原因: // ShowSelectedMembers.cshtml @model MyApp.Models.MembersViewModel @for (int m = 0; m < Model.Members.Count; m++) { <input type="hidden" asp-for="@Model.Members[m].Id" /> <input type="hidden" asp-for="@Model.Members[m

此代码可能有什么原因:

// ShowSelectedMembers.cshtml
@model MyApp.Models.MembersViewModel

@for (int m = 0; m < Model.Members.Count; m++)
{
    <input type="hidden" asp-for="@Model.Members[m].Id" />
    <input type="hidden" asp-for="@Model.Members[m].FirstName" />
    <input type="hidden" asp-for="@Model.Members[m].LastName" />
    <span>[debug-info: m = @m, id = @Model.Members[m].Id]</span>
    <span>@Model.Members[m].LastName</span>,
    <span>@Model.Members[m].FirstName</span>
}
成员[0].Id在隐藏字段中的值如何为6652,在隐藏字段中的值如何为6653

这是视图的控制器方法:

public IActionResult ShowSelectedMembers(MembersViewModel vm)
{
    vm.Members = vm.Members.Where(s => s.Selected).OrderBy(o => o.LastName).ThenBy(o => o.FirstName).ToList();
    return View(vm);
}
这是将整个成员列表发送到控制器方法的表单:

// Index.cshtml
@model MyApp.Models.MembersViewModel

<form asp-action="ShowSelectedMembers">
    <button type="submit">View selection</button>
    @if (Model.Members.Any())
    {
        for (int i = 0; i < Model.Members.Count; i++)
        {
            Model.Members[i].Id
            Model.Members[i].FirstName
            Model.Members[i].LastName
            <input type="checkbox" asp-for="@Model.Members[i].Selected" />
            <input type="hidden" asp-for="@Model.Members[i].Id" />
            <input type="hidden" asp-for="@Model.Members[i].FirstName" />
            <input type="hidden" asp-for="@Model.Members[i].LastName" />
        }
    }
</form>
更新

要澄清此操作的流程,请执行以下操作:

“索引”视图包含一个表单,该表单包含列表中每个成员的选中复选框

此表单将整个成员列表传递给控制器方法ShowSelectedMembers

控制器方法筛选出选定集为false的成员,并将选定成员传递给视图ShowSelectedMembers

该视图显示已筛选的列表,该列表现在已损坏数据

更新2

我将控制器方法更改为此,创建了一个新实例,而不是重用viewmodel:

public async Task<IActionResult> ShowSelectedMembers(MembersViewModel vmIn)
{
    List<int> memberIds = new List<int>();
    foreach (MemberViewModel member in vmIn.Members.Where(s => s.Selected).ToList())
    {
        memberIds.Add(member.Id);
    }
    List<Member> selectedMembers = await db.Members
        .Where(s => memberIds.Contains(s.Id))
        .ToListAsync();
    MembersViewModel vmOut = new MembersViewModel {
        Members = auto.Map<List<MemberViewModel>>(selectedMembers)
    };
    return View(vmOut);
}

例如,手动生成输入字段,而不是使用asp。在第一个示例中,您可以添加ModelState.Clear,它将提供您想要的结果

public IActionResult ShowSelectedMembers(MembersViewModel vm)
{
    ModelState.Clear();
    vm.Members = vm.Members.Where(s => s.Selected).OrderBy(o => o.LastName).ThenBy(o => o.FirstName).ToList();
    return View(vm);
}

然而,我会遵循这里的建议,采用PRG模式——发布表单,然后重定向到GET操作。如果无法从数据库中重新水化模型,则需要将模型存储在TempData store中。

这是该页面的首次新加载吗?或者您以前提交过表单吗?@Jasen所讨论的视图是由另一个视图索引上的表单提交调用的。如果我只是在“索引”视图中选择列表顶部的成员,这似乎是可行的,但如果我选择列表下一个成员,则“成员1”信息似乎会随所选成员一起发送。@Jasen请参阅问题底部的“更新”。与其将视图模型作为返回值重复使用,创建一个新实例并返回筛选后的集合。@Jasen我试过了,但没用。见更新2。
public async Task<IActionResult> ShowSelectedMembers(MembersViewModel vmIn)
{
    List<int> memberIds = new List<int>();
    foreach (MemberViewModel member in vmIn.Members.Where(s => s.Selected).ToList())
    {
        memberIds.Add(member.Id);
    }
    List<Member> selectedMembers = await db.Members
        .Where(s => memberIds.Contains(s.Id))
        .ToListAsync();
    MembersViewModel vmOut = new MembersViewModel {
        Members = auto.Map<List<MemberViewModel>>(selectedMembers)
    };
    return View(vmOut);
}
@*<input type="text" asp-for="@Model.Members[i].Id" />*@
@{
    string _id = $"Members_{i}__Id";
    string _name = $"Members[{i}].Id";
    string _value = Model.Members[i].Id.ToString();
}
<input type="hidden"
       data-val="true"
       data-val-required="The Id field is required." 
       id=@_id
       name=@_name
       value=@_value />
public IActionResult ShowSelectedMembers(MembersViewModel vm)
{
    ModelState.Clear();
    vm.Members = vm.Members.Where(s => s.Selected).OrderBy(o => o.LastName).ThenBy(o => o.FirstName).ToList();
    return View(vm);
}