2016-06-04 4 views
2

У меня возникли проблемы с публикацией модели, содержащей словарь. Каждый раз, когда я получаю модель при моем действии контроллера, все значения являются нулевыми (действительно только значения словаря, которые мне нужны), и я не уверен, как это решить или почему это происходит. Ниже вы можете найти мой взгляд (исключая не относящиеся к делу части), мой контроллер и модель просмотра, которую я использую. Идея здесь состоит в том, чтобы передать словарь, связывающий пользователей с ролями, позволить администратору редактировать различные роли пользователя, а затем передать информацию обратно контроллеру, чтобы обновить БД с новой информацией о роли. Мне удавалось сериализовать IEnumerables в прошлом (списки и т. Д.) Таким образом, но не могу заставить его работать для словаря. Вся помощь приветствуется.C# MVC- публикация viewmodel, которая содержит словарь

The View:

@model RecipeManager.ViewModels.AdminViewModel 

@{ 
    ViewBag.Title = "Index"; 
} 
<h2>Admin</h2> 
@using (Html.BeginForm("UpdateRoles", "Admin", FormMethod.Post)) 
{ 
    <div> 
     @for (int i = 0; i < Model.UsersAndRoles.Count; i++) 
     { 
      <strong>@Model.UsersAndRoles.ElementAt(i).Key.UserName</strong> 
      @Html.DropDownListFor(m => m.UsersAndRoles.ElementAt(i).Value, Model.RoleTypes, Model.UsersAndRoles.ElementAt(i).Value, new { @class = "form-control" }) 
     } 
    </div> 
    <input type="submit" value="Update Roles" /> 
} 

Пример HTML произвел имя пользователя и администратора роли выпадающее меню:

<strong>[email protected]</strong> <select class="form-control" id="Value" name="Value"><option value="">Cook</option> 
<option value="1">Admin</option> 
<option value="2">Cook</option> 
<option value="3">Retail</option> 
</select> 

контроллер действия (в AdminController):

[AuthorizeUser(Activity = "ViewAdmin")] 
[HttpPost] 
public ActionResult UpdateRoles(AdminViewModel vm) 
{ 
    return View("Index"); 
} 

И ViewModel (AdminViewModel):

namespace RecipeManager.ViewModels 
{ 
    public class AdminViewModel 
    { 

    public SelectList RoleTypes { get; set; } 

    public String SelectedRole { get; set; } 

    public String InviteEmailAddress { get; set; } 

    public Dictionary<ApplicationUser, string> UsersAndRoles { get; set; } 


    } 
} 
+0

Не могли бы вы показать HTML, который испускается этим кодом бритвы? – Crowcoder

+0

Вы проходите сериализованный объект? – Karolis

+0

Возможный дубликат [Правильный, идиоматический способ использования настраиваемых шаблонов редактора с IEnumerable-моделями в ASP.NET MVC] (http://stackoverflow.com/questions/25333332/correct-idiomatic-way-to-use-custom-editor- templates-with-ienumerable-models-in) – GSerg

ответ

2

Вы генерируя <select> элемент с атрибутом имени (name="Value"), который не имеет никакого отношения к вашей собственности, которая является Dictionary. Для привязки к Dictionary нужны входные данные для свойств Key и Value, а также потому, что их коллекция также нуждается в индексировании. В вашем случае это становится еще хуже, потому что ваш Key является сложным объектом.

Для связывания, сгенерированный HTML необходимо будет

<input type="hidden" name="UsersAndRoles[0].Key.Id" value="...." /> 
<input type="hidden" name="UsersAndRoles[0].Key.UserName" value="...." /> 
.... // more hidden inputs for each property of ApplicationUser 
<select name="UsersAndRoles[0].Value"> 
    <option value="">Cook</option> 
    .... 
</select> 

<input type="hidden" name="UsersAndRoles[1].Key.Id" value="...." /> 
<input type="hidden" name="UsersAndRoles[1].Key.UserName" value="...." /> 
.... // more hidden inputs for each property of ApplicationUser 
<select name="UsersAndRoles[1].Value"> 
    <option value="">Cook</option> 
    .... 
</select> 

Стандартных HtmlHelper методов не будет делать это из коробки (хотя вы можете создать свой собственный метод расширения для генерации HTML). Но это будет намного проще, если вы просто создадите модель своего представления для представления того, что вы хотите редактировать в представлении.

Однако его непонятная из вашей модели текущего вида, к которой вы хотите привязываться. У вас есть public String SelectedRole { get; set; } property, который не используется, и DictionaryValue is typeof string, но значения SelectListItem являются typeof int. Кроме того, использование метода DropDownListFor() будет работать некорректно, если вы не используете EditorTemplate вместе с AdditionalViewData или не создаете новый IEnumerable<SelectListItem>, как описано в this answer. (обратите внимание, что ни один из параметров не имеет атрибута selected, хотя третий вариант («cook») должен быть). Также обратите внимание, что третий параметр DropDownListFor() генерирует опцию null, поэтому он должен быть "Please select" или аналогичным, а не значением текущей роли.

Ваш вид модели (на основе кода вида вы показали) должны быть

public class AdminViewModel 
{ 
    public SelectList RoleTypes { get; set; } 
    public List<UserRoleViewModel> UserRoles { get; set; } 
} 
public class UserRoleViewModel 
{ 
    public int ID { get; set; } 
    public string UserName { get; set; } 
    [Display(Name = "Role")] 
    [Required(ErrorMesage = "Please select a role")] 
    public int SelectedRole { get; set; } 
} 

Затем создать EditorTemplate в /Views/Shared/EditorTemplates/UserRoleViewModel.cshtml

@model UserRoleViewModel 
@Html.HiddenFor(m => m.ID) 
@Html.HiddenFor(m => m.UserName) 
<strong>@Html.DisplayFor(m => m.UserName)</strong> 
@Html.LabelFor(m => m.SelectedRole) 
@Html.DropDownListFor(m => m.SelectedRole, (SelectList)ViewData["RoleTypes"], "Please Select") 
@Html.ValidationMessageFor(m => m.SelectedRole) 

, а затем в главном окне

@model RecipeManager.ViewModels.AdminViewModel 
.... 
@using (Html.BeginForm("UpdateRoles", "Admin", FormMethod.Post)) 
{ 
    @Html.EditorFor(m => m.UserRoles, new { RoleTypes = Model.RoleTypes }) 
    <input type="submit" value="Update Roles" /> 
} 
Смежные вопросы