MVC 3: заполнение выпадающего списка пользователями в роли участника ASP «Менеджер»

#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. Дарин: Ваш подход действительно хорош.