1
votes

I have a strongly-typed view (bound to userController) which lists the User with particular Roles and below that I have a dropdownlist containing all the Roles with a submit button. All I need is to assign new Role to that User. The ActionResult method is in UserRolesController. how can i pass userId and RoleId on button click to ActionResult Method.

ActionResult Method in UserRolesController:

[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");
    }

View like this:

@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>

Model Entities:

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; }
}

On Button click nothing happens. Is is possible to pass the values as parameters from one model view to another?

1
You have not shown you model or the GET method. Does you model contain a property named Roles? You should not give the model property and the ViewBag property the same name. - user3559349
Your also passing `IEnumerable<user> to the model. But expecting to pass back just one user (which one?) and you have no controls inside you form so there is nothing post back anyway. - user3559349
I have updated the code. yes I have declared the Roles property in users model. - naeemmalik
I have dropdownlist bound to Roles entity. I can get the roleId from it. Other i need the userId (id) in my case to pass as parameter. - naeemmalik
How can I pass back the values I got from the LINQ query and listed in my view? any suggestion ? - naeemmalik

1 Answers

0
votes

There are numerous problems with you code. In particular your passing IEnumerable<user> to the model not including or rendering any controls in your form so nothing posts back, and in any case you cant post back UserRole because its a complex object and a dropdownlist only returns a single value. And there is no point displaying all roles in the dropdown, then checking if its already been selected on postback - just include only those roles that the user does not already have when you create the view. And assigning a message to ViewBag and then redirecting is pointless - its immediately lost.

Create a view model to represent what you want to display and edit (note I have excluded properties for displaying existing roles)

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; }
}

Controller

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);
}

View

@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" />
}

Post method

[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
}