将视图模型返回到 HttpPost ActionResult



我正在尝试更新我的 ASP.NET Identity项目中的用户角色集合,但我目前陷入困境,因为我在发送到我的[HttpPost]方法的ViewModel中获得了一个空UsersAndRolesDictionary属性。

这是我的观点模型,UpdateUserRolesViewModel

namespace Project_Name.Models
{
    public class UpdateUserRolesViewModel
    {
        public IDictionary<ApplicationUser, ICollection<IdentityUserRole>> UsersAndRolesDictionary { get; set; } // <-- This is returning null currently
    }
}

这是我HomeController的方法:

[Authorize(Roles = "Admin")]
public ActionResult RoleManager()
{
    ViewBag.Message = "Role Management Page";
    var databaseContext = new ApplicationDbContext();           // Get the Database Context
    var users = databaseContext.Users.Include(u => u.Roles);    // Get all users from the Database and their Roles
    var newDict = new Dictionary<ApplicationUser, ICollection<IdentityUserRole>>();
    // Add each user and their roles to the dictionary
    foreach (var user in users)
    {
        newDict.Add(user, user.Roles);
    }
    // Update the ViewModel with the collection of users and roles
    var updateUserRolesViewModel = new UpdateUserRolesViewModel {UsersAndRolesDictionary = newDict};
    return View(updateUserRolesViewModel);
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UpdateUsersRolesAsync(UpdateUserRolesViewModel updateUserRolesViewModel)
{
    try
    {
        //TODO: Attempt to update the user roles or delete the user
        return View("RoleManager");
    }
    catch
    {
        //TODO: Properly catch errors
        return View("RoleManager");
    }
}

这是我的观点,RoleManager

@using Project_Name.Models
@model UpdateUserRolesViewModel
@{
    ViewBag.Title = "Role Manager";
    var databaseContext = new ApplicationDbContext();   // Get the Database Context
    var roles = databaseContext.Roles;                  // Get all Roles from the database, use this to compare against
}
<h2>@ViewBag.Title</h2>
<div class="row">
    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
        @using (Html.BeginForm("UpdateUsersRolesAsync", "Home", FormMethod.Post))
        {
            @Html.AntiForgeryToken()
            <div class="form-group">
                <div class="table-responsive">
                    <table class="table table-striped table-bordered table-hover">
                        <thead>
                            <tr>
                                <th>Email</th>
                                <th>Roles</th>
                                <th>Delete User?</th>
                            </tr>
                        </thead>
                        <tbody>
                            @{
                                int i = 0; // Used to make unique IDs for the user's table row, and deleteUserCheckbox
                                int j = 0; // Used to make unique IDs for the role checkboxes
                                foreach (var user in Model.UsersAndRolesDictionary.Keys)
                                {
                                    i++;
                                    <tr id="userTableRow_@i">
                                        <td>@user.Email</td>
                                        <td>
                                            @* Show each role availabe as a checkbox. Check them if the user has that role. *@
                                            @foreach (var role in roles)
                                            {
                                                @Html.CheckBox("userRoleCheckbox_" + j++, user.Roles.Any(identityUserRole => identityUserRole.RoleId.Contains(role.Id)))
                                                <span>@role.Name</span>
                                                <br />
                                            }
                                        </td>
                                        <td>
                                            @Html.CheckBox("deleteUserCheckbox_" + i)
                                            <span>Delete User</span>
                                        </td>
                                    </tr>
                                }
                            }
                        </tbody>
                    </table>
                </div>
                @* Reset and Submit buttons *@
                <div class="col-lg-2 col-lg-push-8 col-md-2 col-md-push-8 col-sm-2 col-sm-push-8 col-xs-2 col-xs-push-8">
                    <input type="reset" class="btn btn-danger btn-block" value="Reset" />
                </div>
                <div class="col-lg-2 col-lg-push-8 col-md-2 col-md-push-8 col-sm-2 col-sm-push-8 col-xs-2 col-xs-push-8">
                    <input type="submit" class="btn btn-primary btn-block" value="Submit" />
                </div>
            </div>
        }
    </div>
</div>

我正在使用字典UsersAndRolesDictionary来收集所有用户及其角色,然后枚举以表格的形式生成我的视图。

我希望更改潜在多个用户的复选框值,然后将更新的 ViewModel 传递给我的 [HttpPost] UpdateUsersRolesAsync 方法以更新我的用户角色,但现在我得到了 UsersAndRolesDictionary 属性的空值,我不确定为什么或如何修复它。


感谢斯蒂芬·穆克在评论中的链接/答案,我能够回答这个问题。请参阅下面的回答帖子。

按照 Stephen Muecke 在评论中的建议,我得到了一个有效的 ViewModel 要返回。

添加/更新了三个组合在一起的视图模型:

首先是RoleViewModel

public class RoleViewModel
{
    public string Id { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

第二UserViewModel

public class UserViewModel
{
    public string Id { get; set; }
    public string Email { get; set; }
    public List<RoleViewModel> RoleViewModels { get; set; }
    public bool DeleteUser { get; set; } // Doesn't work yet, might be in the wrong place
}

最后第三个是UpdateUserRoleViewModel的更新版本:

public class UpdateUserRolesViewModel
{
    public int Id { get; set; }
    public List<UserViewModel> UserViewModels { get; set; }
}

在我的更新HomeController中,再次是方法:

[Authorize(Roles = "Admin")]
public ActionResult RoleManager()
{
    ViewBag.Message = "Role Management Page";
    var databaseContext = new ApplicationDbContext();                   // Get the Database Context
    var users = databaseContext.Users.Include(u => u.Roles).ToList();   // Get all users from the Database and their Roles
    // Create the UpdateUserRolesViewModel
    var updateUserRolesViewModel = new UpdateUserRolesViewModel
    {
        Id = 0, // Not sure what else the Id would be
        UserViewModels = new List<UserViewModel>()
    };
    // Add each user to the UserViewModels list
    for (int i = 0; i < users.Count(); i++)
    {
        var userViewModel = new UserViewModel
        {
            Id = users.AsEnumerable().ElementAt(i).Id,
            Email = users.AsEnumerable().ElementAt(i).UserName,
            RoleViewModels = new List<RoleViewModel>(),
            DeleteUser = false
        };
        // Add each role from the Roles table to the RoleViewModels list, check if user has that role
        foreach (var role in databaseContext.Roles)
        {
            var roleViewModel = new RoleViewModel
            {
                Id = role.Id,
                Name = role.Name,
                IsSelected = users.AsEnumerable().ElementAt(i).Roles.Any(identityUserRole => identityUserRole.RoleId.Contains(role.Id))
            };
            userViewModel.RoleViewModels.Add(roleViewModel);
        }
        updateUserRolesViewModel.UserViewModels.Add(userViewModel);
    }
    return View(updateUserRolesViewModel);
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UpdateUsersRolesAsync(UpdateUserRolesViewModel updateUserRolesViewModel)
{
    try
    {
        // Attempt to update the user roles
        foreach (var user in updateUserRolesViewModel.UserViewModels)
        {
            // Delete user
            //TODO: Prompt user to confirm deletion if one or more people are being deleted
            if (user.DeleteUser)
            {
                var userToDelete = await UserManager.FindByIdAsync(user.Id);    // Get the ApplicationUser object of who we want to delete
                await UserManager.DeleteAsync(userToDelete);                    // Delete the user
                continue;                                                       // Don't try to update the roles of a deleted user.
            }
            // Remove all roles from the User
            var rolesToRemove = await UserManager.GetRolesAsync(user.Id);
            await UserManager.RemoveFromRolesAsync(user.Id, rolesToRemove.ToArray());
            // Add roles to the User
            foreach (var roleViewModel in user.RoleViewModels.Where(r => r.IsSelected))
            {
                await UserManager.AddToRoleAsync(user.Id, roleViewModel.Name);
            }
        }
        return RedirectToAction("RoleManager");
    }
    catch
    {
        //TODO: Properly catch errors
        return RedirectToAction("RoleManager");
    }
}

最后,这是我的观点,角色经理

@using Project_Name.ViewModels
@model UpdateUserRolesViewModel
@{
    ViewBag.Title = "Role Manager";
}
@* Debugging text *@
@foreach (var user in Model.UserViewModels)
{
    <div>User ID: @user.Id</div>
    <div>User Name: @user.Email</div>
    <p>
        @foreach (var roleViewModel in user.RoleViewModels.Where(r => r.IsSelected))
        {
            <div>Role ID: @roleViewModel.Id</div>
            <div>Role Name: @roleViewModel.Name</div>
        }
    </p>
    <hr />
}
<h2>@ViewBag.Title</h2>
<div class="row">
    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
        @using (Html.BeginForm("UpdateUsersRolesAsync", "Home", FormMethod.Post))
        {
            @Html.AntiForgeryToken()
            @Html.HiddenFor(m => m.Id)
            <div class="form-group">
                <div class="table-responsive">
                    <table class="table table-striped table-bordered table-hover">
                        <thead>
                            <tr>
                                <th>Email</th>
                                <th>Roles</th>
                                <th>Delete User?</th>
                            </tr>
                        </thead>
                        <tbody>
                            @for (int i = 0; i < Model.UserViewModels.Count; i++)
                            {
                                <tr id="userTableRow_@i">
                                    <td>
                                        @Html.HiddenFor(m => m.UserViewModels[i].Id)
                                        @Html.HiddenFor(m => m.UserViewModels[i].Email)
                                        @Model.UserViewModels[i].Email
                                    </td>
                                    <td>
                                        @for (int j = 0; j < Model.UserViewModels[i].RoleViewModels.Count; j++)
                                        {
                                            @Html.HiddenFor(m => m.UserViewModels[i].RoleViewModels[j].Id)
                                            @Html.HiddenFor(m => m.UserViewModels[i].RoleViewModels[j].Name)
                                            @Html.CheckBoxFor(m => m.UserViewModels[i].RoleViewModels[j].IsSelected)
                                            @Html.DisplayTextFor(m => m.UserViewModels[i].RoleViewModels[j].Name)
                                            <br/>
                                        }
                                    </td>
                                    <td>
                                        @Html.CheckBoxFor(m => m.UserViewModels[i].DeleteUser)
                                        @Html.DisplayNameFor(m => m.UserViewModels[i].DeleteUser)
                                    </td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </div>
                @* Reset and Submit buttons *@
                <div class="col-lg-2 col-lg-push-8 col-md-2 col-md-push-8 col-sm-2 col-sm-push-8 col-xs-2 col-xs-push-8">
                    <input type="reset" class="btn btn-danger btn-block" value="Reset" />
                </div>
                <div class="col-lg-2 col-lg-push-8 col-md-2 col-md-push-8 col-sm-2 col-sm-push-8 col-xs-2 col-xs-push-8">
                    <input type="submit" class="btn btn-primary btn-block" value="Submit" />
                </div>
            </div>
        }
    </div>
</div>

现在,这会更新用户的角色,并删除它们(尽管没有确认检查,所以要小心!

相关内容

  • 没有找到相关文章

最新更新