【问题标题】:How to extend identity user properties with a select box如何使用选择框扩展身份用户属性
【发布时间】:2015-04-09 22:17:32
【问题描述】:

我对 razor 和 mvc 控制器的经验很少。我想在我的注册视图中添加一个下拉框。我从网上的一些例子中尝试了一些不同的东西,但我不知道如何通过应用程序用户访问我需要的类。我想添加公司列表。我真的迷失了通过帐户视图模型。我从公司类中删除了关系,因为我必须清理它。不知道这需要什么。一个用户只能拥有一家公司。

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> 
        GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        var userIdentity = await manager
            .CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    }

    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }

公司类

 public class Company
{
    public int CompanyId { get; set; }
    public string CompanyName { get; set; }

    public List<Document> Documents { get; set; }
}

帐户视图模型

public class RegisterViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    [Required]
    [Display(Name = "UserName")]
    public string UserName { get; set; }
    [Required]
    [Display(Name = "CompanyName")]
    public int CompanyId { get; set; }
    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }

    //Property for the options
    public IEnumerable<SelectListItem> CompanyOptions(string selected)
    {
        //This is just static - get it from somewhere else (database?)
        return new List<SelectListItem>{ 
            new SelectListItem{ Text = "Company 1", Value = "1", Selected = selected.Equals("1") },
            new SelectListItem{ Text = "Company 2", Value = "2", Selected = selected.Equals("2") }
         };
    }
}

查看

<div class="form-group">
  @Html.LabelFor(model => model.CompanyId, new { @class = "control-label col-md-2" })
 <div class="col-md-10">
   @Html.DropDownFor(m => m.CompanyId, Model.CompanyOptions(Model.CompanyId), null)
  </div>

错误信息

描述:在编译服务此请求所需的资源期间发生错误。请查看以下特定错误详细信息并适当修改您的源代码。 编译器错误消息:CS1061:“System.Web.Mvc.HtmlHelper”不包含“DropDownFor”的定义,并且无法找到接受“System.Web.Mvc.HtmlHelper”类型的第一个参数的扩展方法“DropDownFor”(您是否缺少 using 指令或程序集引用?) 源错误: 第 41 行:@Html.LabelFor(model => model.CompanyId, new { @class= "control-label col-md-2" }) 第 42 行: 第 43 行:@Html.DropDownFor(m => m.CompanyId, Model.CompanyOptions(Model.CompanyId), null) 第 44 行: 第 45 行: 块引用

新错误

编译器错误消息:CS0121:以下方法或属性之间的调用不明确:'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable, System.Collections.Generic.IDictionary)”和“System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System. Collections.Generic.IEnumerable,字符串)'

用户管理控制器

// GET: /Users/Create
    public async Task<ActionResult> Create()
    {
        //Get the list of Roles
        ViewBag.RoleId = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Name");
        return View();
    }
 // POST: /Users/Create
    [HttpPost]
    public async Task<ActionResult> Create(RegisterViewModel userViewModel, params string[] selectedRoles)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser 
            {
                UserName = userViewModel.UserName,
                Email = userViewModel.Email,
                CompanyId = userViewModel.CompanyId,
                Name = userViewModel.Name
            };


                user.UserName = userViewModel.UserName;
                user.Email = userViewModel.Email;
                user.CompanyId = userViewModel.CompanyId;
                user.Name = userViewModel.Name;

            // Then create:
            var adminresult = await UserManager.CreateAsync(user, userViewModel.Password);

            //Add User to the selected Roles 
            if (adminresult.Succeeded)
            {
                if (selectedRoles != null)
                {
                    var result = await UserManager.AddToRolesAsync(user.Id, selectedRoles);
                    if (!result.Succeeded)
                    {
                        ModelState.AddModelError("", result.Errors.First());
                        ViewBag.RoleId = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Name");
                        return View();
                    }
                }
            }
            else
            {
                ModelState.AddModelError("", adminresult.Errors.First());
                ViewBag.RoleId = new SelectList(RoleManager.Roles, "Name", "Name");
                return View();

            }
            return RedirectToAction("Index");
        }
        ViewBag.RoleId = new SelectList(RoleManager.Roles, "Name", "Name");
        return View();
    }

帐户控制器

// GET: /Account/Register
    [AllowAnonymous]
    public ActionResult Register()
    {
        return View();
    }
// POST: /Account/Register
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.UserName, Email = model.Email, CompanyId = model.CompanyId, Name = model.Name };


            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                var callbackUrl = Url.Action("ConfirmEmail", "Account", 
                    new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                await UserManager.SendEmailAsync(user.Id, 
                    "Confirm your account", 
                    "Please confirm your account by clicking this link: <a href=\"" 
                    + callbackUrl + "\">link</a>");
                ViewBag.Link = callbackUrl;
                return View("DisplayEmail");
            }
            AddErrors(result);
        }

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

注册视图模型

public class RegisterViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    [Required]
    [Display(Name = "UserName")]
    public string UserName { get; set; }
    [Required]
    [Display(Name = "CompanyName")]
    public int CompanyId { get; set; }
    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }

    //Property for the options
    public IEnumerable<SelectListItem> CompanyOptions(int selected)
    {
        //This is just static - get it from somewhere else (database?)
        return new List<SelectListItem>{ 
            new SelectListItem{ Text = "Company 1", Value = "1", Selected = selected.Equals("1") },
            new SelectListItem{ Text = "Company 2", Value = "2", Selected = selected.Equals("2") }
         };
    }
}

【问题讨论】:

    标签: c# asp.net-mvc entity-framework razor asp.net-identity-2


    【解决方案1】:

    第二条错误消息是由于将null 用于DropDownListFor() 的第三个参数而导致的。调用是模棱两可的,因为它是一个接受string labelOption 的重载和一个接受object htmlAttributes 的重载

    删除第三个参数(或者如果您想要一个选项标签,请将其设为string,例如string.Empty,或"-Please select-"

    您也不应该设置SelectListItemSelected 属性。 @Html.DropDownListFor(m =&gt; m.CompanyId, ... 绑定到属性CompanyId,因此如果CompanyId 的值与其中一个选项的值匹配,则将选择该选项(在上面的代码中,如果CompanyId=2,则第二个选项将是选择)。 Selected 属性的值被忽略。相反,将CompanyOptions 更改为属性

    public IEnumerable<SelectListItem> CompanyOptions { get; set; }
    

    在控制器中

    public ActionResult Create()
    {
      RegisterViewModel model = new RegisterViewModel();
      model.CompanyId = 2; // set this if you want to display a specific company
      ConfigureViewModel(model);
      return View(model);
    }
    
    public ActionResult Create(RegisterViewModel model)
    {
      if(!ModelState.IsValid)
      {
        ConfigureViewModel(model);
        return View(model);
      }
      // Save and redirect
    }
    
    private void ConfigureViewModel(RegisterViewModel model)
    {
      model.CompanyOptions = new List<SelectListItem>()
      {
        new SelectListItem() { Text = "Company 1", Value = "1" },
        new SelectListItem() { Text = "Company 2", Value = "2" }
      };
    }
    

    如果您从数据库中访问公司,则更有可能

    model.CompanyOptions = new SelectList(db.Companies, "ID", "Name")
    

    【讨论】:

    • 好的,看起来不错。不过我确实需要一些帮助。我正在使用一个包含用户角色和 UserAdmin 控制的种子项目。所以我习惯了更多的控制器。你能帮忙放置你的代码吗?我更新了我的帖子
    • 我不明白你的评论。你有什么问题?您的 Create() 方法看起来很奇怪 - 除了两次设置 user 的值之外,params string[] selectedRoles 是什么?为什么selectedRoles 不是视图模型的属性,你如何为selectedRoles 渲染控件?而且您编辑的内容完全重复(我认为)您在原始版本中的RegisterViewModel,所以我有点困惑。无论如何,它似乎与您的原始问题或您遇到的错误无关,所以它应该是一个新问题
    • 这就是问题所在,这是我使用的一个种子项目,因为它已经准备好用户角色和用户管理。我真的不明白它是如何设置的。我只习惯有一个帐户控制器,它有一个帐户控制器和一个 userAdmin 控制器。所以当我试图插入你的东西时,我有点迷失了。我会在一段时间内再次处理它。我仍然计划感谢您的帮助。谢谢
    【解决方案2】:

    您需要将公司列表添加到您的注册模型中,在视图中将其呈现给用户,然后获取所选值并将其应用到您的发布操作中。

    型号:

    //Property for the options
    public IEnumerable<SelectListItem> CompanyOptions(string selected)
    {
        //This is just static - get it from somewhere else (database?)
        return new List<SelectListItem>{ 
            new SelectListItem{ Text = "Company 1", Value = "1", Selected = selected.Equals("1") },
            new SelectListItem{ Text = "Company 2", Value = "2", Selected = selected.Equals("2") }
        };
    }
    

    现在我们可以将它渲染到视图中:

    <div class="form-group">
        @Html.LabelFor(model => model.CompanyId, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(m => m.CompanyId, Model.CompanyOptions(Model.CompanyId), null)
        </div>
    </div>
    

    现在您可以在Register 操作中使用模型上的CompanyId 属性。

    【讨论】:

    • 不用担心,但现在得到这个 'TransparentEnergy.Models.RegisterViewModel.CompanyOptions(string)' 的最佳重载方法匹配有一些无效参数
    • 尝试将参数从字符串更改为整数。
    猜你喜欢
    • 1970-01-01
    • 2015-09-01
    • 2020-12-18
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 2015-10-17
    • 1970-01-01
    相关资源
    最近更新 更多