【问题标题】:IEnumerable<SelectListItem> error in Simple Membership in ASP.NET MVC 5ASP.NET MVC 5 中的简单成员中的 IEnumerable<SelectListItem> 错误
【发布时间】:2015-10-30 01:39:10
【问题描述】:

我在 ASP.NET MVC 5 中使用 Simple Membership 来使用我现有的 SQL Server。在注册页面中,我使用下拉框来填充用户角色。在我的帐户控制器中,我使用 [HttpGet] 和 [HttpPost] 进行注册操作。当我运行我的网络应用程序并转到注册页面时,我可以看到我的 DropDownBox 填充了来自我的 SqlServer 的数据。

但是当我尝试创建新用户并选择一个角色时,我得到了错误;

"不存在具有键 'roleName' 的 'IEnumerable' 类型的 ViewData 项"

这是我的帐户控制器代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SimpleMemberShip.Models;
using WebMatrix.WebData;
using System.Web.Security;

namespace SimpleMemberShip.Controllers
{
    public class AccountController : Controller
    {
        // ****** REGISTER PAGE ACTION ******
        [HttpGet]
        public ActionResult Register()
        {
            //Roles for DropDown Box
            IEnumerable<SelectListItem> RolesList = new System.Web.Mvc.SelectList(System.Web.Security.Roles.GetAllRoles(), "roleName");
            ViewData["roleName"] = RolesList;
            return View();
        }

        // ****** REGISTER PAGE ACTION with PARAMETERS ******
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Register(Register registerdata, string RoleName)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password);
                    System.Web.Security.Roles.AddUserToRole(registerdata.Username, RoleName);
                    return RedirectToAction("Index", "Home");
                }
                catch (MembershipCreateUserException exception)
                {
                    ModelState.AddModelError("", "Warning: Username exist...");
                    return View(registerdata);
                }
            }
            ModelState.AddModelError("", "Warning: Username exist....");
            return View(registerdata);
        }
    }
}

这是我的 Register.cshtml 代码的样子:

@using SimpleMemberShip.Models
@model Register

@{
    ViewBag.Title = "Register";
}

<h2>New User Registration</h2>
<br />
<div>
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary()
        <label>User Name:</label>
        @Html.TextBoxFor(m => m.Username, new { @class = "form-control" })
        <br />
        <label>User Password:</label>
        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        <br />
        <label>Roles</label>
        @Html.DropDownList("roleName", (System.Web.Mvc.SelectList)ViewBag.roleName, "Select a Role")
        <br />
        <br />
        <button class="btn btn-primary">Register</button>
    }
</div>

有人知道我哪里出错了吗?

亲切的问候,

【问题讨论】:

  • 当 POST 失败并且您尝试 return View(registerdata) 时,ViewBag 为空,因此无法填充下拉列表。顺便说一句,您应该在 Register ViewModel 中包含选择列表,而不是使用 ViewBag。

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


【解决方案1】:

最有可能发生的情况是您在注册用户的方式中出现了某种错误,并且验证失败。在这种情况下,您将返回相同的视图,这很好:

return View(registerdata);

但是,您不会重新填充视图所依赖的 ViewData["roleName"] 元素。由于 ASP.NET MVC 不维护任何类型的状态,因此需要在每个请求上重新填充此元素。所以考虑这样做,就像你之前在 GET 操作中做的那样,错误应该会消失。

附带说明,您正在混合将数据从控制器传递到视图、模型和 ViewData 的两种方式。这不是很容易维护和明显,所以我建议你只坚持模型方法。这应该不是很难 - 添加角色名称列表作为模型的属性,并确保在每次请求时对其进行初始化。

【讨论】:

    【解决方案2】:

    在您的 HttpPost 操作中,如果发生某些错误,或者您的模型验证失败,您会将相同的模型返回到相同的视图。因此,您需要再次使用角色列表集合重新加载ViewData["roleName"],因为您的视图正试图从中读取以加载下拉列表。

    请记住,HTTP 是无状态的。 ASP.NET MVC 不像 Web 表单那样工作,它在多个 http 请求(表单帖子)中以视图状态存储表单数据

    我的建议是不要使用动态的东西,比如 ViewBag 和 ViewData。您应该使用强类型视图模型将数据从您的操作方法传输到您的视图。

    所以创建一个类似的视图模型

    public class CreateUser
    {
      public string UserName {set;get;}
      public string Password{set;get;}
      public List<SelectListItem> RolesList {set;get;}
      public int SelectedRoleId {set;get;}
    }
    

    在您的 GET 操作方法中,您将获取所有角色(可以是 Role 类或某些自定义类的集合),将其转换为 SelectListItem 的集合并将其分配给 RolesList 的属性创建用户对象

    public ActionResult Register()
    {
      var vm=new CreateUser();     
      vm.RolesList =GetRoles();
    
      return View(vm);     
    }
    private List<SelectListItem> GetRoles()
    {
       var allRoles = System.Web.Security.Roles.GetAllRoles();        
       return allRoles.Select(s => new SelectListItem
            {
                Value = s.roleId.ToString(),
                Text = s.roleName
            });
    }
    

    在你的剃刀视图中绑定到CreateUser 类。

    @using YourNamespace.CreateUser
    @using(Html.Beginform())
    {
       @Html.TextBoxFor(s=>s.UserName)
       @Html.TextBoxFor(s=>s.Password)
       @Html.DropDownListFor(x=> x.SelectedRoleId, Model.RolesList,"Select")
       <input type="submit" />
    }
    

    现在在您的 Http 发布操作方法中,确保在将发布的模型返回到同一视图之前重新加载 RolesList 集合(如果模式验证失败或发生异常)

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Register(CreateUser model)
    {
       if (ModelState.IsValid)
       {
          try
          {
           // to do : Save something
          // read model.UserName & model.SelectedRoleId etc. 
            return RedirectToAction("Index", "Home");
          }
          catch (MembershipCreateUserException exception)
          {
              ModelState.AddModelError("", "Warning: Username exist...");
              //Reload the data now
              model.RolesList =GetRoles();
              return View(model);
          }
       }
       ModelState.AddModelError("", "Warning: Username exist....");
      //Reload the data now
       model.RolesList =GetRoles();
       return View(model);
    }  
    

    【讨论】:

    • 嗨,Shyju,我尝试使用您的代码,但在 RoleManger 上出现错误,因为“当前上下文中不存在名称 'RoleManger'”。 s.RoleId 和 s.RoleName 也有错误。它说“字符串不包含 RoleId 和 RoleName 的定义”。我正在使用 VS2015 社区并使用 .Net Framework 4.5 创建没有身份验证的 MVC。我为我的项目安装了 Install-Package WebMatrix.Data 和 Install-Package WebMatrix.WebData。以及安装包 Microsoft.AspNet.WebHelpers 和安装包 Microsoft.AspNet.WebPages.Data。这就是为什么我找不到 RoleManager。有什么帮助吗?
    • @NTMS:不需要该行。我更新了答案。同样在GetRoles 方法中,将 RoleID 和 RoleName 替换为您从Roles.GetAllRoles() 方法获得的对象的属性
    • 感谢您的评论。 System.Web.Security.Roles.GetAllRoles();只返回一个 my sql serverb 数据库表数据。我找不到任何属性。是的,我的 sql 表只包含 RoleId 和 RoleName。 !!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-07
    • 2020-03-14
    • 2016-05-11
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 2021-12-23
    相关资源
    最近更新 更多