繁体   English   中英

在POST上将模型绑定到单选按钮

[英]Bind Model to Radio Buttons on POST

我正在尝试扩展使用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>

但是,将表单提交回时,该模型永远无效,因为该角色从未绑定。 (或者至少是我所相信的)任何想法?

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

//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方法中查找适当的角色。

我对此进行了调查(因为我有一个可用的方法,甚至对理论进行了检验),这是不可能的。 您可以将所选对象的任何子属性绑定到您的视图模型,但不能将其整体绑定。

这是我来自堆栈溢出的参考

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

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

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

例如,您需要创建一个视图模型,该模型的属性表示要在视图中显示/编辑的内容(假设IdentityRole type具有属性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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM