2015-05-06 3 views
0

Я пытаюсь расширить форму регистрации пользователя, которая сгенерирована с использованием EF6 и MVC, я хочу иметь возможность отображать список ролей пользователей, которые отображаются в виде переключателей, которые я считаю Я сделал. Однако проблема в том, что когда я отправляю форму обратно контроллеру, это не привязывает выбранную опцию к модели представления. Что я делаю не так?Bind Model to Radio Buttons on POST

My View Model:

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> 

Однако, когда форма отправлена ​​обратно, модель никогда не действует, поскольку роль никогда не связана , (Или, по крайней мере, это то, что я верю) Любые идеи?

ответ

0

Вы не хотите иметь радиокнопки, привязанные к списку значений, вам необходимо изменить вы модель в список ролей и выбранной роль, как этот

//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 контроллера.

+0

Да, я согласен с вашей записью, поскольку у меня все еще возникают проблемы с привязкой к IndentityRole. Я начинаю думать, что это невозможно. Я мог просто привязаться к веревке. Однако я хочу быть более динамичным. –

0

Я изучил это (даже проверил теорию, так как у меня был один доступный), и это невозможно. Вы можете привязать любое свойство sub выбранного объекта к вашей модели представления, но не полностью.

Вот мой reference из переполнения стека.

0

Элементы управления Html (ввод, текстовое поле, выберите) отправляют обратно свои пары имя/значение. В вашем случае данные формы, связанные с переключателем, будут UserRoles: someValue.

Предполагая, что ваш метод POST является public ActionResult Register(RegisterViewModel model), то DefaultModelBinder первым инициализирует экземпляр RegisterViewModel затем находит имя данных, которые соответствуют форме пара/значения и пытается установить значение свойства UserRoles к строке "someValue" которая, конечно, терпит неудачу, потому что 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.