#asp.net-mvc-3 #razor
#asp.net-mvc-3 #razor
Вопрос:
Итак, я внедряю членство в ASP и управление ролями в своем приложении. У меня также есть вторая таблица пользователей со всей информацией, не связанной с членством. Я установил электронную почту в качестве имени пользователя в членстве и в качестве внешнего ключа в моей таблице пользователей.
Я настраиваю страницу регистрации, чтобы включить выпадающий список, чтобы при создании учетной записи можно было выбрать менеджера. Список менеджеров создается путем поиска всех пользователей-участников с ролью «Менеджер», а затем создания коллекции пользователей, где внешние ключи соответствуют результатам.
List<string> managerNames = new List<string>(Roles.GetUsersInRole("Manager"));
var managers = from m in _db.Users where managerNames.Contains(m.Email) select m;
ViewBag.managers = managers;
Теперь я должен использовать эту коллекцию пользователей для заполнения выпадающего списка, на мой взгляд, с атрибутом Name, установленным на «ManagerID» (в соответствии с моей моделью регистрации), значением каждого параметра, установленным на первичный ключ пользователя, и отображаемым текстом в выпадающем списке, показывающим DisplayName модели пользователя.
Я могу выполнить утомительную задачу по циклическому просмотру моей коллекции «менеджеры» и заполнению отдельного SelectListItem, а затем передать SelectListItem в @Html.DropDown("ManagerID", newSelectListItem)
, но это кажется чрезмерным. Есть ли более прямой (или приемлемый) способ сделать это?
Редактировать
Я добавил это в свой контроллер
var selectList = new List<SelectListItem>();
foreach (var manager in managers)
{
selectList.Add(new SelectListItem(){
Value = manager.UserID.ToString(),
Text = manager.DisplayName,
Selected = false
});
}
ViewBag.managers = selectList;
и это, на мой взгляд
@Html.DropDownList("ManagerID", (List<SelectListItem>)ViewBag.managers)
и это работает. Это все еще лучший подход?
Комментарии:
1. Насколько это утомительно или чрезмерно? Перебор вашего объекта managers звучит для меня довольно тривиально.
2. Если это лучший подход, я с радостью это сделаю. Я просто не знал, был ли это лучший подход.
Ответ №1:
Это все еще лучший подход?
Нет. Лучший подход — использовать модели просмотра и забыть о существовании ViewBag / ViewData. Итак, начните с разработки модели представления, которая будет соответствовать требованиям вашего представления (отображать ddl менеджеров):
public class MyViewModel
{
[Required]
public int? SelectedManagerId { get; set; }
public IEnumerable<SelectListItem> Managers { get; set; }
}
а затем пусть ваше действие контроллера заполнит эту модель представления и передаст ее в представление:
public ActionResult Foo()
{
var managers = ... query your repository to get them
var model = new MyViewModel
{
Managers = managers.Select(x => new SelectListItem
{
Value = x.UserID.ToString(),
Text = x.DisplayName
})
};
return View(model);
}
и, наконец, в вашем строго типизированном представлении:
@model MyViewModel
...
@Html.DropDownListFor(
x => x.SelectedManagerId,
Model.Managers,
"-- Select a manager --"
)
Поэтому каждый раз, когда вы используете ViewBag / ViewData в ASP.NET Приложения MVC должен прозвучать сигнал тревоги, сообщающий вам, что есть лучший способ.
Комментарии:
1. Я получаю ошибку LINQ, которую выражение LINQ не разрешает. toString(). Я пытаюсь выяснить, как это решить. Мысли?
2. @Watermark Studios, позвоните
.ToList()
в конце вашего запроса LINQ и перед построением модели представления, чтобы быстро получить переменную messages.3. Дарин: Ваш подход действительно хорош.