2009-06-05 1 views
0

Я пытаюсь понять что-то немного лучше, будучи новым для C#, .NET 3.5 и MVC.Ошибка при попытке заполнить выпадающий список во время действия «GET» create

Я бегу через пример MVC NerdDinner, и если вы посмотрите на ViewModel здесь: http://nerddinnerbook.s3.amazonaws.com/Part6.htm#highlighter_662935

Вы можете увидеть список стран и как он получает, это, кажется, работает хорошо, но я пытался сделать подобное ниже, используя LINQ, и у меня возникают проблемы с использованием подхода SelectList, хотя он наследуется от интерфейса IEnumerable.

У меня есть таблица задач с внешним ключом в таблице состояния. Приведенный ниже код дает мне исключение NullReferenceException, когда я делаю GET при создании действия. Я вижу, что анонимный объект задачи не имеет статуса. Поэтому мне, вероятно, нужно проверить его, но я не понимаю, как это не делается для примера NerdDinner?

 public class TaskViewModel { 
     // Properties 

     public Task Task { get; private set; } 
     public SelectList Status { get; private set; } 

     // Constructor 
     public TaskViewModel(Task task) { 
      TaskRepository taskRepo = new TaskRepository(); 
      Task = task; 
      Status = new SelectList(taskRepo.GetStatus(), Task.Status.description); 
     } 

    } 

     // 
     // GET: /Tasks/Create 

     public ActionResult Create() 
     { 
      Task task = new Task(); 

      return View(new TaskViewModel(task)); 
     } 


//Code from TaskRepository 

     private TaskManagerDataContext db = new TaskManagerDataContext(); 

     public IQueryable<Status> GetStatus() { 
      return from status in db.Status 
        orderby status.description 
        select status; 
     } 

Я сделал еще один подход с использованием LINQ для типа выпадающего списка и населения ниспадающих работ, но я все же проверить, если он выбирает правильное значение, как только пост сделан и подробное представление возвращаются. Я также задаюсь вопросом, должно ли это быть каким-то образом, как перемещаться в мой репозиторий, а не иметь класс в моем контроллере, делающий такие вещи?

Вот код:

//In TaskViewModel Class 
     public IEnumerable<SelectListItem> Types { get; private set; } 

//In TaskViewModel constructor 

       IList<NPType> types = taskRepo.GetTypes().ToList(); 

      Types = 
       from type in types 
       select new SelectListItem { 
        Selected = (type.typeId == task.typeId), 
        Text = type.description, 
        Value = type.typeId.ToString() 
       }; 

//The TaskForm partial View that is used for the Create action of the TaskController 
      <p> 
       <label for="type">type:</label> 
       <%= Html.DropDownList("Type", Model.Types)%> 
       <%= Html.ValidationMessage("type", "*") %> 
      </p> 
      <p> 
       <label for="status">status:</label> 
       <%= Html.DropDownList("Status", Model.Status)%> 
       <%= Html.ValidationMessage("status", "*") %> 
      </p> 

и вид TaskForm наследует System.Web.Mvc.ViewUserControl

ответ

0

Моя попытка попытаться понять это лучше.

//controller code creating a select list in the viewmodel class. 
//taskRepo.GetStatus() returns an IQueryable<Status> 
     Status = new SelectList(taskRepo.GetStatus(), Task.Status); 

//MVC Framework SelectList class constructor and ToEnumerable method 
      public SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue) 
      : base(items, dataValueField, dataTextField, ToEnumerable(selectedValue)) { 
      SelectedValue = selectedValue; 
     } 

     private static IEnumerable ToEnumerable(object selectedValue) { 
      return (selectedValue != null) ? new object[] { selectedValue } : null; 
     } 

Я могу видеть, что SelectList использует базовый класс MultiSelectList и конструктор здесь:

 public MultiSelectList(IEnumerable items, string dataValueField, string dataTextField, IEnumerable selectedValues) { 
     if (items == null) { 
      throw new ArgumentNullException("items"); 
     } 

     Items = items; 
     DataValueField = dataValueField; 
     DataTextField = dataTextField; 
     SelectedValues = selectedValues; 
    } 

При запуске этого проекта HTML определяется как:

<select id="Status" name="Status"><option>NPTaskManager.Models.Status</option> 
<option>NPTaskManager.Models.Status</option> 
<option>NPTaskManager.Models.Status</option> 
<option>NPTaskManager.Models.Status</option> 
</select> 

Какие следует ожидать.

Если изменить код контроллера на:

Status = new SelectList(taskRepo.GetStatus(), Task.Status.statusId.ToString(), Task.Status.description); 

Тогда я получаю NullReferenceException.Поскольку это не ArgumentNullException Мне кажется, что корень исключения не является первым аргументом SelectList. Я пытаюсь понять, как все это происходит? Это потому, что Task.Status нужно добавить в Task в действие create контроллера?

Я изменю этот код, чтобы использовать подход LINQ, который я использовал для задачи выше, все, что я пытаюсь достичь, - это некоторое понимание того, что происходит.

+0

Вы могли решить tht проблему? если да, то как? –

0

Что в конструкторе задачи? Какова ценность .typeId для вновь созданной задачи? Это пустая ссылка?

Для модели просмотра, отправленной на ваш объект «Создать представление», вы не должны пытаться установить выбранный элемент списка, если ваш конструктор задач (или другой код инициализации) не задает значения по умолчанию для этих свойств. Если task.typeId имеет значение NULL, тогда ваш код, создающий список выбора, получит ошибку.

0

Я понимаю, что я получу нулевое значение для типа или статуса, если я не добавлю значение к вновь созданной задаче. То, что я не понимаю, и которое я не прояснил, - это ниже. Вы можете видеть, что модель представления имеет свойство «Страны», и для ее выбранного значения установлено значение «Ужин». Страна ... теперь Dinner.Country не устанавливается в действии create. Так почему же это не дает нулевого исключения?

//viewmodel code 
      public DinnerFormViewModel(Dinner dinner) { 
      Dinner = dinner; 
      Countries = new SelectList(PhoneValidator.Countries, Dinner.Country); 
     } 

//controller code 
     public ActionResult Create() { 

      Dinner dinner = new Dinner() { 
       EventDate = DateTime.Now.AddDays(7) 
      }; 

      return View(new DinnerFormViewModel(dinner)); 
     } 

//view code 
      <p> 
      <label for="Country">Country:</label> 
      <%= Html.DropDownList("Country", Model.Countries) %>     
      <%= Html.ValidationMessage("Country", "*") %> 
     </p> 
Смежные вопросы