MVC:在复选框列表中显示角色,然后保存它们

时间:2011-01-05 02:25:44

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

我有一个页面,其中角色显示在复选框列表中,您可以选择您希望用户拥有哪些角色,然后单击按钮进行保存。

这是我的模特:

public class RegisterModel
{
    [DisplayName("Roles")]
    public string[] Roles
    {
        get
        {
            return System.Web.Security.Roles.GetAllRoles();
        }
        set { }
    }
}

我的观点:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<WebUI.Models.RegisterModel>" %>

<% using (Html.BeginForm()) { %>
    <% foreach(string role in Model.Roles) { %>
        <input type="checkbox" value="<%: role %>" /> <%: role %>
    <% } %>

    <p>
        <input type="submit" value="Register" />
    </p>
<% } %>

我控制器的功能:

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

[HttpPost]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        //save roles
        return RedirectToAction("Index", "Home");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

当我尝试查看我的页面时,我在foreach语句中得到一个“对象引用未设置为对象的实例”错误,表示Model.Roles为空。

  1. 我是否通过我的模型正确传递角色?或者我应该通过我的Controller操作将角色作为ViewData传递?
  2. 如果我将角色作为ViewData传递而不是通过我的模型传递,那么当我提交表单时如何访问所选项目以便我可以致电Roles.AddUsersToRoles()

4 个答案:

答案 0 :(得分:3)

首先,当您获得页面时,您没有将模型传递给视图。这导致空引用异常。它应该是:

[HttpGet]
public ActionResult Register() {

  //create an instance of your model however you are doing that
  var model = new RegisterModel();

  //pass your model instance to your view
  return View(model);
}

其次,您需要在输入中添加name属性,以便MVC模型绑定在表单发布时传递数据。

  <% foreach(string role in Model.Roles) { %>
    <input type="checkbox" name="Roles" value="<%: role %>" /> <%: role %>
  <% } %>

但是,由于您的Roles属性似乎没有setter,您可能应该创建一个包含角色的视图模型,因此您的代码应该如下所示:

查看模型

public class RegisterViewModel {
  public string[] Roles { get; set; }
  //...other properties
}

查看

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<WebUI.ViewModels.RegisterViewModel>" %>

<% using (Html.BeginForm()) { %>
  <% foreach(string role in Model.Roles) { %>
    <input type="checkbox" name="Roles" value="<%: role %>" /> <%: role %>
  <% } %>

  <p><input type="submit" value="Register" /></p>
<% } %>

控制器

[HttpGet]
public ViewResult Index() {
  var model = new RegisterViewModel();
  model.Roles = System.Web.Security.Roles.GetAllRoles(); //or however you populate your roles
  return View(model);
}

[HttpPost]
public ActionResult Index(RegisterViewModel model) {
  string[] roles = model.Roles //the selected roles are here
  //....
}

答案 1 :(得分:0)

你可以做一些事情(暂时没有这样做,全部来自记忆):

<% foreach(string role in Model.Roles) { %>
    <input type="checkbox" name="roles" value="<%: role %>" /> <%: role %>
<% } %>

在你的控制器中:

[HttpPost]
public ActionResult Register(string[] roles)
{
    if (ModelState.IsValid)
    {
        //save roles
        return RedirectToAction("Index", "Home");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

现在,对于每个选中的复选框,您将获得数组中的值。

答案 2 :(得分:0)

这只是部分答案,但我可以解释空引用异常位。

您尚未创建RegisterModel类的实例。您的视图需要WebUI.Models.RegisterModel,但您未在此代码中提供过。

尝试:

public ActionResult Register() { return View(new RegisterModel()); }

或将您的角色属性设为静态:

public static string[] Roles

以这种方式访问​​您的视图:

foreach(string role in RegisterModel.Roles)

答案 3 :(得分:0)

对于可测试性和完整性,我会将您的模型更改为不伸出并尝试直接获取角色,而是在构造函数中获取角色列表。