簡體   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