【问题标题】:Bind Model to Radio Buttons on POST将模型绑定到 POST 上的单选按钮
【发布时间】:2015-05-06 16:59:15
【问题描述】:

我正在尝试扩展使用 EF6 和 MVC 生成的用户注册表单,我希望能够显示显示为单选按钮的用户角色列表,我相信我已经做到了。但是我遇到的麻烦是当我将表单发布回控制器时,它没有将选定的选项绑定回视图模型。我做错了什么?

我的视图模型:

public class RegisterViewModel
{
    [Required]
    [Display(ResourceType = typeof(ResourceStrings), Name = "Username")]
    [StringLength(50, ErrorMessageResourceType = typeof(ResourceStrings), ErrorMessageResourceName = "MinLengthValidation", MinimumLength = 4)]
    public string Username { get; set; }

    [Required]
    [Display(ResourceType = typeof(ResourceStrings), Name = "FirstName")]
    [StringLength(50, ErrorMessageResourceType = typeof(ResourceStrings), ErrorMessageResourceName = "MinLengthValidation", MinimumLength = 2)]
    public string FirstName { get; set; }

    [Required]
    [Display(ResourceType = typeof(ResourceStrings), Name = "Surname")]
    [StringLength(50, ErrorMessageResourceType = typeof(ResourceStrings), ErrorMessageResourceName = "MinLengthValidation", MinimumLength = 2)]
    public string Surname { get; set; }

    //Other fields removed to save space

    [Required]
    [Display(Name = "Roles")]
    public IEnumerable<IdentityRole> UserRoles { get; set; }
}

我有一个想要传递给视图的身份角色列表,如下所示:

// GET: /Account/Register
    [AllowAnonymous]
    public ActionResult Register()
    {
        var model = new RegisterViewModel();
        model.UserRoles =  new RoleManager<IdentityRole>(new RoleStore<IdentityRole>()).Roles.ToList();

        return View(model);
    }

在视图中我显示的角色是这样的:

     <div class="panel-body">
            @foreach (var item in Model.UserRoles)
            {
                <div class="col-md-8">
                    <div>
                        @Html.RadioButtonFor(m => m.UserRoles, item.Name)
                        @Html.DisplayFor(m => item.Name, new { @class = "col-md-3 control-label" })
                    </div>
                </div>
            }
            @Html.ValidationMessageFor(m => m.UserRoles, "", new { @class = "text-danger" })
        </div>

但是,当表单被提交回来时,模型永远不会有效,因为角色永远不会被绑定。 (或者至少我是这么认为的)有什么想法吗?

【问题讨论】:

    标签: c# asp.net-mvc razor asp.net-identity model-binding


    【解决方案1】:

    您不想将单选按钮绑定到值列表,您需要将模型更改为角色列表和所选角色,如下所示

    //Other fields removed to save space
    
    [Required]
    [Display(Name = "Role")]
    public IdentityRole UserRole { get; set; }
    
    [Display(Name = "Roles")]
    public IEnumerable<IdentityRole> UserRoles { get; set; }
    

    然后你像这样创建单选按钮

    @Html.RadioButtonFor(m => m.UserRole, item.Name)
    

    这会将选定的值回传到 UserRole 属性。

    注意:我认为您还需要使用单选按钮的值才能将其填充回 UserRole,因为我认为 item.Name 不起作用。你可能想用名称回发到一个字符串字段,然后在控制器的 post 方法中查找正确的角色。

    【讨论】:

    • 是的,我同意您的意见,因为我仍然无法绑定到 IndentityRole。我开始认为这是不可能的。我可以绑定到一个字符串。但是我想要更有活力。
    【解决方案2】:

    我研究了这个(甚至测试了这个理论,因为我有一个可用的),这是不可能的。您可以将所选对象的任何子属性绑定到您的视图模型,但不能将整个对象绑定。

    这是我来自堆栈溢出的reference

    【讨论】:

      【解决方案3】:

      Html 控件(输入、文本区域、选择)回发它们的名称/值对。在您的情况下,与单选按钮关联的表单数据将是 UserRoles: someValue

      假设您的 POST 方法是 public ActionResult Register(RegisterViewModel model)DefaultModelBinder 首先初始化 RegisterViewModel 的实例,然后找到匹配的表单数据名称/值对并尝试将属性 UserRoles 的值设置为字符串 @987654326 @ 当然失败了,因为UserRoles 是一个复杂的对象,而UserRoles 变成了null

      您无法将 html 控件绑定到复杂对象,除非您创建自定义 ModelBinder 和/或 ValueProviders,即使这样它也只会设置您模型的一个属性,因为您只回发一个值。

      您需要创建一个视图模型,其属性表示您希望在视图中显示/编辑的内容,例如(假设 typeof IdentityRole 具有属性 int ID

      public class RegisterViewModel
      {
        [Required]
        [Display(ResourceType = typeof(ResourceStrings), Name = "Username")]
        [StringLength(50, ErrorMessageResourceType = typeof(ResourceStrings), ErrorMessageResourceName = "MinLengthValidation", MinimumLength = 4)]
        public string Username { get; set; }
        ....
      
        // For binding the selected roles
        [Required(ErrorMessage = "Please select a role")]
        public int ID SelectedRole { set; set; }
      
        // For displaying the available roles 
        [Display(Name = "Roles")]
        public IEnumerable<IdentityRole> UserRoles { get; set; }
      }
      

      然后在视图中

      @model yourAssembly.RegisterViewModel
      @using (Html.BeginForm())
      {
        ....
        foreach(var role in Model.UserRoles)
        {
          @Html.RadioButtonFor(m => m.SelectedRole, role.ID, new { id = role.Name })
          <label for="@role.Name">@role.Name</label>
        }
        @Html.ValidationMessageFor(m => m.SelectedRole)
        ....
      }
      

      当您回帖时,您可以从模型SelectedRole 属性中获取所选角色的 ID。

      【讨论】:

        猜你喜欢
        • 2013-06-29
        • 2021-07-19
        • 2017-06-22
        • 2020-01-19
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多