繁体   English   中英

将Viewmodel返回到HttpPost ActionResult

[英]Return Viewmodel to HttpPost ActionResult

我正在尝试更新我的ASP.NET Identity项目中的用户角色集合,但由于当前在发送给我的[HttpPost]方法的ViewModel中获取了一个空的UsersAndRolesDictionary属性,因此我陷入了UsersAndRolesDictionary

这是我的ViewModel, 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在评论中的链接/答案,我才能够回答这个问题。 请参阅下面的我的答案。

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

添加/更新了三个结合在一起的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");
    }
}

最后,这是我的视图, 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>

现在,这将更新用户的角色,并将其删除(尽管没有确认检查,所以请当心!)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM