Ваша проблема связана с отложенным выполнением запросов LINQ. Вам нужно с нетерпением инициализировать коллекцию:
public class UserRoleModel
{
public IEnumerable<RoleViewModel> AllRoles { get; set; }
public UserModel user { get; set; }
public UserRoleModel()
{
this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel
{
Name = r
}).ToList();
this.user = new UserModel();
}
}
Обратите внимание на .ToList()
вызов:
this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel
{
Name = r
}).ToList();
А вот и объяснение. Когда вы пишете:
this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel
{
Name = r
});
В данный момент запрос не выполняется. Строится только дерево выражений, но фактический запрос выполняется только тогда, когда что-то начинает перебирать коллекцию. И что начинает повторяться? Сначала это вид. Внутри представления вы используете шаблон редактора для этой коллекции:
@Html.EditorFor(x => x.AllRoles)
Поскольку AllRoles является свойством коллекции, ASP.NET MVC автоматически выполнит итерацию и отобразит шаблон редактора для каждого элемента коллекции. Так что это работает для правильной визуализации представления.
Теперь давайте посмотрим, что происходит, когда форма размещена. Вы отправляете сообщение в действие Create, и связыватель модели по умолчанию запускается. Конструктор вызывается, но поскольку нечего перебирать свойство AllRoles, на этот раз запрос не выполняется. Фактически он выполняется позже внутри действия и значения теряются.
По этой причине я бы рекомендовал вам не инициализировать ваши модели представления внутри конструкторов. Было бы лучше сделать это внутри соответствующих действий контроллера:
public class UserRoleModel
{
public IEnumerable<RoleViewModel> AllRoles { get; set; }
public UserModel user { get; set; }
}
и затем:
public ActionResult Create()
{
var model = new UserRoleModel
{
AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel
{
Name = r
}).ToList(),
user = new UserModel()
};
return View(model);
}