1

I'm just looking for a better way to do the following :

I've got an html select :

<form method="post" action="/Account/ChangeUserRole">
  <select name="Val" onchange="this.form.submit();" class="span2">
   @foreach (var r in ViewBag.UserRoles)
   {
    @if (u.UserRole.ID == r.ID)
   {
    <option selected="selected" value="@u.ID/@r.ID">@r.Name</option>
   }
   else
   {
    <option value="@u.ID/@r.ID">@r.Name</option> // <-- better way?
   }
  }
  </select>
  </form>

I'm posting it as "userid/roleid" and on the controller side doing a string.Split on / to split u.ID and r.ID

I would like to know if it's possible to post it so my controller get's them in this way :

[HttpPost]
public IActionResult ChangeUserRole(int UserID, int RoleID)

Instead of this witchcraft:

[HttpPost]
public IActionResult ChangeUserRole(string Val)
{
    char[] splitChar = new char[] { '/' };
    string[] s = Val.Split(splitChar);
    int UserID = Convert.ToInt32(s[0]);
    int RoleID = Convert.ToInt32(s[1]);
}

Sorry for the long post. Hope my question makes sense. I'm not such a big fan of html helpers.

Side note: I'm using MVC 6, ASP 5 - RC1

Appreciate the help

Cheers!

4
  • Why not use the Tag helpers ? This post explains how to use Select Tag helper to render a dropdown. Commented Feb 2, 2016 at 20:18
  • Thanks for the reply. I like the new way of using tag helpers ie : <label asp-for="Name">Name:</label> Not a fan of : @Html.LabelFor(m => p.Name, "Name:") Commented Feb 2, 2016 at 20:26
  • It feels more friendly to html designers. And it doesn't hide implementation. Commented Feb 2, 2016 at 20:27
  • Ah oke.. I see. I can change it to accept a ViewModel containing those two values.. Jeez man, I'm doing that almost every day.. Completely missed that :( And then : "asp-items=" ties it together. Commented Feb 2, 2016 at 20:40

1 Answer 1

4

The best solution is to use the TagHelpers to build your dropdown. Let's start by creating a view model specific to this view.

public class UserRoleEditVm
{
    public List<SelectListItem> Roles { set; get; }
    public int RoleId { set; get; }
    public int UserId { set; get; }
}

In your get action, create an object of this, load the property values and send it to the view.

public IActionResult Create()
{
   // User Id and Role list is hard coded for demo. You may replace it with real data.

    var v = new UserRoleEditVm {UserId = 45};
    v.Roles = new List<SelectListItem>
    {
        new SelectListItem {Value = "1", Text = "Admin"},
        new SelectListItem {Value = "2", Text = "Editor"},
        new SelectListItem {Value = "3", Text = "Reader"}
    };
    return View(v);
}

And in your view, which is strongly typed to our view model, we will like Tag helpers to for creating the HTML markup.

@model UserRoleEditVm    
<form asp-action="ChangeUserRole" asp-controller="Account">

    <select asp-for="RoleId" asp-items="@Model.Roles">
        <option>Please select one role</option>
    </select>
    <input  type="hidden"asp-for="UserId"/>
    <input type="submit"/>

</form>

And in your HttpPost action method, you can use an object of our view model as the parameter and the Model binder will map the posted form values to property values of that object.

[HttpPost]
public ActionResult ChangeUserRole(UserRoleEditVm model)
{
    var userId = model.UserId;
    var roleId = model.RoleId;
    // to do : Do something with the above 2 values
    // to do :Save and redirect (PRG pattern)
    // return RedirectToAction("Success");
}
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect! Nice & neat.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.