【问题标题】:ListBoxFor is not fully updating the viewmodel on submitListBoxFor 未在提交时完全更新视图模型
【发布时间】:2026-01-24 01:05:02
【问题描述】:

我已经能够像这样创建视图模型(请忽略它包含另一个视图模型,这将在我解决当前问题后修复:)):

public class UserViewModel
{
    #region Variables
    private SecUserViewModel user;
    private string[] assignedRolesIds;
    private List<SecRoleViewModel> availableRoles;
    #endregion

    #region Properties
    public SecUserViewModel User 
    { 
        get { return this.user; }
        set { this.user = value; }

    }
    public string Guid
    {
        get { return this.user.Guid.ToString(); }
        set { this.user.Guid = value; }
    }

    public string UserName
    {
        get { return this.user.UserName; }
        set { this.user.UserName = value; }
    }

    public string Email
    {
        get { return this.user.Email; }
        set { this.user.Email = value; }
    }

    public byte[] AuthDigest
    {
        get { return this.user.AuthDigest; }
        set { this.user.AuthDigest = value; }
    }

    public bool IsUsingTempPasswd
    {
        get { return this.user.IsUsingTempPasswd; }
        set { this.user.IsUsingTempPasswd = value; }
    }
    public DateTime? LastLogin
    {
        get { return this.user.LastLogin; }
        set { this.user.LastLogin = value; }
    }

    public DateTime? PasswordChanged
    {
        get { return this.user.PasswordChanged; }
        set { this.user.PasswordChanged = value; }
    }
    public string[] AssignedRolesIds
    {
        get { return this.assignedRolesIds; }
        set { this.assignedRolesIds = value; }

    }
    public List<SecRoleViewModel> AvailableRoles
    {
        get { return this.availableRoles; }
        set { this.availableRoles = value; }

    }
    #endregion

    #region Constructor

    public UserViewModel()
    {
        User = new SecUserViewModel();
        AssignedRolesIds = null;
        AvailableRoles = new List<SecRoleViewModel>(0);
    }

    public UserViewModel(SecUserViewModel secUser, List<SecRoleViewModel> roleList, List<SecRoleViewModel> availableList)
    {
        User = secUser;
        AssignedRolesIds = roleList.Select(r => r.Role.Guid.ToString()).ToArray();
        AvailableRoles = availableList;
    }

    #endregion
}

我的控制器有一个编辑操作。在“GET”上,我通过 viewmodel 并正确显示它,包括多选列表和预选值。但是当我“发布”“编辑”时,传回的 UserViewModel 具有“AssignedRolesIds”和“AvailableRoles”空,尽管其他所有内容都已填充。当我检查 FormCollection 对象时,有“AssignedRolesIds”作为键存在。

我的观点是这样的:

@model DocuLive.ViewModels.UserViewModel

@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_AdminPage.cshtml";
}

<h2>Edit</h2>
<div class="error-message">@TempData["Fail"]</div>
<div class="success-message">@TempData["Success"]</div>
@using (Html.BeginForm("Edit", "User", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>SecUser</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.User.Guid)
        </div>
        <div class="editor-field">
            @Html.DisplayFor(model => model.User.Guid)
            @Html.HiddenFor(model => model.User.Guid)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.UserName)
        </div>
        <div class="editor-field">
            @Html.DisplayFor(model => model.User.UserName)
            @Html.HiddenFor(model => model.User.UserName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User.Email)
            @Html.ValidationMessageFor(model => model.User.Email)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.IsUsingTempPasswd)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User.IsUsingTempPasswd)
            @Html.ValidationMessageFor(model => model.User.IsUsingTempPasswd)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.LastLogin)
        </div>
        <div class="editor-field">
            @Html.DisplayFor(model => model.User.LastLogin)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.PasswordChanged)
        </div>
        <div class="editor-field">
            @Html.DisplayFor(model => model.User.PasswordChanged)
        </div>
        <div class="hidden-field">
            @Html.HiddenFor(model => model.User.AuthDigest)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.AssignedRolesIds)
        </div>
        <div class="editor-field">
            @Html.ListBoxFor(x => x.AssignedRolesIds, new MultiSelectList(Model.AvailableRoles, "Guid", "RoleName"), new { Multiple = "multiple", @class = "multi-select-list" }) 
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Users")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

谁能告诉我为什么只传回与 ListBoxFor 相关的值(有一个空值)?

提前致谢

【问题讨论】:

  • 这个场景你应该使用 Html.DropDownListFor(...)。例如,如果你想我可以添加答案。
  • 我需要角色是“多项选择” - 如果 DropDownListFor 能做到这一点,我会很乐意使用它,所以我会很感激你解决我的问题的四个...

标签: asp.net-mvc-4 razor asp.net-mvc-viewmodel html.listboxfor


【解决方案1】:

似乎问题在于将字符串数组值绑定到复杂对象的字符串 id 值(在我的情况下为角色) - 但我最终找到了解决方法。诀窍是拥有这个方法的签名:

[HttpPost]
public ActionResult Edit(UserViewModel user, string [] assignedRolesIds)

然后你会看到这个:

@Html.ListBox("AssignedRolesIds",new MultiSelectList(Model.AvailableRoles, "Guid", "RoleName"),new { Multiple = "multiple", @class = "multi-select-list"})

使用此解决方案,您必须将“assignedRolesIds”重新分配回 UserViewModel 上的“AssignedRolesIds”属性,但这只有两行(包括检查数组是否为空或 null)。

【讨论】: