如何使用 select 框扩展身份用户属性

How to extend identity user properties with a select box

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

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; }

公司Class

 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>

错误信息

Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately. Compiler Error Message: CS1061: 'System.Web.Mvc.HtmlHelper' does not contain a definition for 'DropDownFor' and no extension method 'DropDownFor' accepting a first argument of type 'System.Web.Mvc.HtmlHelper' could be found (are you missing a using directive or an assembly reference?) Source Error: Line 41: @Html.LabelFor(model => model.CompanyId, new { @class = "control-label col-md-2" }) Line 42: Line 43: @Html.DropDownFor(m => m.CompanyId, Model.CompanyOptions(Model.CompanyId), null) Line 44: Line 45: Blockquote

新错误

Compiler Error Message: CS0121: The call is ambiguous between the following methods or properties: 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable, System.Collections.Generic.IDictionary)' and 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable, string)'

用户管理控制器

// 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") }
         };
    }
}

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

型号:

//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 属性。

第二条错误消息是由于使用 null 作为 DropDownListFor() 的第三个参数造成的。该调用不明确,因为它是一个接受 string labelOption 的重载和一个接受 object htmlAttributes

的重载

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

您也不应设置 SelectListItemSelected 属性。 @Html.DropDownListFor(m => 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")