Creating dropdownlist from values in database

2019-07-04 12:35发布

问题:

I have a table called Roles with three fields

  1. Guid RoleId
  2. string RoleName
  3. string Description

In my register.cshtml view I want to have a dropdownlist which shows the list of RoleName from Roles table. I also need to be able to get that value and work with it, like assigning the Role to user, which will in done in controller. My view currently looks like the one below, i'm using model as AspNetUser but it doesn't have knowledge about Role which is what I want to show in dropdownlist.

@model Sorama.CustomAuthentiaction.Models.AspNetUser
@{
    ViewBag.Title = "Register";
    Layout = "~/Views/shared/_BootstrapLayout.empty.cshtml";
}

@section Styles{
    <link href="@Url.Content("~/Content/bootstrap.css")" rel="stylesheet" type="text/css" />
}
<div class ="form-signin">

    @using (Html.BeginForm("Register", "Account"))
    {
        @Html.ValidationSummary(true)
        <h2 class="form-signin-heading"> Register </h2>
        <div class ="input-block-level">@Html.TextBoxFor(model=>model.Email, new{@placeholder = "Email"})</div>
        <div class ="input-block-level">@Html.TextBoxFor(model=>model.UserName, new{@placeholder = "UserName"})</div>
        <div class ="input-block-level">@Html.PasswordFor(model=>model.Password, new{@placeholder ="Password"})</div>
        <div class ="input-block-level">@Html.DropDownListFor(//don't know what to do

        <button class="btn btn-large btn-primary" type="submit">Register</button>
    }
</div>

My controller looks like this

   public class AccountController : Controller
    {
        //private readonly IDbContext dbContext;
        //
        // GET: /Account/
        [HttpGet]
        public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        [AllowAnonymous]
        public ActionResult Login(LoginModel model)
        {
            if(Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
            return View(model);
        }

        [HttpGet]
        public ActionResult Register()
        {
            string [] roles = Roles.GetAllRoles();
            return View(roles);
        }

        [HttpPost]
        public ActionResult Register(AspNetUser model)
        {

            return View();
        }

        public ActionResult Index()
        {
            return View();
        }

    }

What do I need to do, to have that dropdownlist?

回答1:

In your controller you need to pass the string[] (IEnumerable<string>) representing your roles into your view somehow...

There are many ways to achieve this, but in your AccountController you could do the following:

public class AccountController : Controller
{
   private IDbContext dbContext;

   public AccountController(IDbContext dbContext)
   {
       // Made up field that defines your GetAllRoles method
       this.dbContext = dbContext;
   }

   public ActionResult Register()
   {
      // Call the GetAllRoles() and capture the result in a variable called roles
      var roles = dbContext.GetAllRoles();

      return View(new AspNetUser {
         Roles = roles
      });
   }
}

Note: I do not enforce the list to be in any form in the controller (I do not specify it should be a select list), I may want to display the items as in a different way and I let the view be flexible by passing the values only and allowing the view to decide how to render the values.

In your View you can then use where you want the dropdown list to appear:

@Html.DropDownListFor(model => model.Roles, Model.Roles
    .Select(role => new SelectListItem { Text = role, Value = role })

As I mentioned, there are many ways to achieve what you are wanting but almost one thing is certain, that with aspnet mvc you will most likely be using the Html helper DropDownListFor MSDN Documentation here:

http://msdn.microsoft.com/en-us/library/system.web.mvc.html.selectextensions.dropdownlistfor(v=vs.108).aspx

EDIT 1:

Create a model to hold the User and Role informations like so:

public class RegisterViewModel
{
   public AspNetUser AspNetUser { get; set; }
   public IEnumerable<string> Roles { get; set; }
}

In the controller it could look like so:

public class AccountController : Controller
{
   private RoleProvider roleProvider;

   public AccountController(RoleProvider roleProvider)
   {
       this.roleProvider = roleProvider;
   }

   public ActionResult Register()
   {
      // Call the GetAllRoles() and capture the result in a variable called roles
      // var roles = roleProvider.GetAllRoles();

      // Or, as you have specified:
      var roles = Roles.GetAllRoles();

      return View(new RegisterViewModel {
         AspNetUser = GetTheAspNetUser(),
         Roles = roles
      });
   }
}

In the View you need to update the model to use:

@model Sorama.CustomAuthentiaction.Models.RegisterViewModel

If you are unwilling/unable to make such a change you could add the list of Roles to the Viewbag:

ViewBag.RoleList = roleProvider.GetAllRoles();

Or as you alluded to:

ViewBag.RoleList = Roles.GetAllRoles();

Then access in the View like so:

@Html.DropDownListFor(model => model.Roles, ViewBag.RoleList
    .Select(role => new SelectListItem { Text = role, Value = role })


回答2:

In a similar scenario, I've done something like this:

private void BagSelectList()
{
    ViewBag.List = new SelectList(
            db.SetOfCandidateValues, 
            "KeyPropertyOfTheSet", 
            "NameOfThePropertyToAppearInTheDropDownList", 
            selectedValue);
}

And in the view:

@Html.DropDownListFor(
            model => model.ForeignKeyProperty, 
            (SelectList)ViewBag.List)

(Of course, if you dislike the ViewBag, you can do it using the strongly typed view model.)