【问题标题】:Passing parameters on button click in strongly-typed view to another controller将强类型视图中的按钮单击参数传递给另一个控制器
【发布时间】:2014-12-01 22:16:29
【问题描述】:

我有一个强类型视图(绑定到 userController),它列出了具有特定角色的用户,下面我有一个下拉列表,其中包含所有角色和一个提交按钮。我只需要为该用户分配新角色。 ActionResult 方法在 UserRolesController 中。如何将按钮单击时的 userId 和 RoleId 传递给 ActionResult 方法。

UserRolesController 中的 ActionResult 方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddRole(UserRole userRole, int roleId, int userId)
    {
        if (!ModelState.IsValid) return View(userRole);

        var check = db.UserRoles.Any(x => x.RoleID == roleId && x.UserID == userId);
        if (check)
            ViewBag.ResultMessage = "This user already has the role specified !";
        else
            db.UserRoles.Add(userRole);
        db.SaveChanges();
        ViewBag.ResultMessage = "User added to the role succesfully !";
        return RedirectToAction("Index");
    }

像这样查看:

@model IEnumerable<MvcAppCRUD.user>

@{
ViewBag.title = "AssignRole";
}

<h2>Assign Role</h2>
@if (!Model.Any())
{
@Html.Label("No Roles assigned for this user")
}
else
{
<table>
    <tr>
        <th>
            @Html.DisplayName("Email")
        </th>
        <th>
            @Html.DisplayName("Role Name")
        </th>
        <th></th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.email)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.RoleName)
            </td>
            <td>
                @Html.ActionLink("Delete", "Delete", new {id = item.id})
            </td>
        </tr>
    }
</table>
}
<hr />
    <div class="display-label">
        @Html.DisplayName("Add Role")
</div>

<div class="display-field">
@Html.DropDownList("Roles", (SelectList) ViewBag.Roles)
</div>

@using (Html.BeginForm("AddRole", "UserRoles"))
{
<div class="message-success">@ViewBag.ResultMessage</div>
}
<p>
    <input type="submit" value="Assign" />
</p>
<p>
@Html.ActionLink("Back to List", "Index")
</p>

模型实体:

public partial class UserRole
{
public int ID { get; set; }
public int UserID { get; set; }
public int RoleID { get; set; }
public int Status { get; set; }

public virtual user Users { get; set; }
public virtual Role Roles { get; set; }
}

public partial class user
{
public user()
{
    Roles = new List<SelectListItem>();
}

public long id { get; set; }
public string email { get; set; }
public string password { get; set; }
public System.DateTime reg_date { get; set; }
public byte validated { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
public int RoleId { get; set; }
public string RoleName { get; set; }

public IEnumerable<SelectListItem> Roles { get; set; }

//public IEnumerable<Role> Roles { get; set; }
}

public partial class Role
{
public int ID { get; set; }
public string RoleName { get; set; }
public string Desc { get; set; }
public int Status { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}

点击按钮没有任何反应。是否可以将值作为参数从一个模型视图传递到另一个模型视图?

【问题讨论】:

  • 你没有展示你的模型或 GET 方法。您的模型是否包含名为Roles 的属性?不应为模型属性和ViewBag 属性赋予相同的名称。
  • 您还将 `IEnumerable 传递给模型。但是希望只传回一个用户(哪一个?),而您的表单内部没有控件,所以无论如何也没有任何回传。
  • 我已经更新了代码。是的,我已经在用户模型中声明了 Roles 属性。
  • 我已将下拉列表绑定到角色实体。我可以从中获取 roleId。其他我需要 userId (id) 在我的情况下作为参数传递。
  • 如何传回从 LINQ 查询中获得并在视图中列出的值?有什么建议吗?

标签: c# asp.net asp.net-mvc-4 razor


【解决方案1】:

您的代码存在许多问题。特别是您将IEnumerable&lt;user&gt; 传递给模型,不包括或呈现您的表单中的任何控件,因此没有任何回传,并且在任何情况下您都不能回发UserRole,因为它是一个复杂的对象,并且下拉列表仅返回一个值。并且没有必要在下拉列表中显示所有角色,然后检查它是否已经在回发时被选中 - 只包括用户在创建视图时还没有的角色。将消息分配给ViewBag 然后重定向是没有意义的——它会立即丢失。

创建一个视图模型来表示您想要显示和编辑的内容(注意我已经排除了用于显示现有角色的属性)

public class UserRoleVM
{
  public int ID { get; set; } // user ID for post back
  public int Name { get; set; } // user name for display in the view
  [Display(Name="Select new role")]
  public int SelectedRole { get; set; }
  public SelectList RoleList { get; set; }
}

控制器

public ActionResult AddRole(int ID)
{
  UserRoleVM model = new UserRoleVM();
  var user = // Get the user based on the ID
  model.ID = ID;
  model.Name = user.??
  var roles = // Get all roles and remove those that the user already has
  model.RoleList = new SelectList(roles, "ID", "RoleName");
  return View(model);
}

查看

@model UserRoleVM
@using(Html.BeginForm())
{
  <h2>@Model.Name</h2> // users name
  @Html.LabelFor(m => m.SelectedRole)
  @Html.DropDownListFor(m => m.SelectedRole, Model.RoleList)
  <input type="submit" value="Add Role" />
}

发布方法

[HttpPost]
public ActionResult AddRole(UserRoleVM model)
{
  // model is now populated with the ID of the user and the ID of the selected role
  // save and redirect
}

【讨论】:

  • 这很有帮助,让一切变得如此清晰,我将在我的应用程序中实现它。您能指导我如何获取未分配给用户的角色。还有一件事,我可以在哪里创建这些 Action 方法?我应该创建新的控制器还是包含在现有的控制器中。感谢并非常感谢您的帮助。
  • 我不知道你的应用很难说它应该在哪里。因为它与User 相关,所以它可能在UserController 中,但是你可以再次使用RolesController 来添加和删除角色。没有硬性规定,您只需要保持一致并保持逻辑,以便其他人可以遵循您的代码。
  • 对于获取未分配给用户的角色,您将首先从数据库中获取所有角色,然后删除已经分配给用户的角色。 This answer 给出了一个使用 .Except() 的简单 linq 表达式的示例,但是有很多方法可以做到(只是不要像 OP 在那个问题中那样做!)。
  • 最后我建议你考虑渲染一个显示所有角色的复选框列表。创建视图时,将检查用户已经拥有的角色。然后管理员可以根据需要检查或取消选中角色并立即保存所有内容,而不是一次添加和/或删除一个角色(这不是一个好的用户体验)。 This answer 可能会指导您。在您的情况下,您的视图模型将具有UserIDList&lt;RolesVM&gt;,其中RoleVM 具有IDNameIsSelected
猜你喜欢
  • 2017-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多