MVC Как перечислить данные второй модели

#model-view-controller #razor #computer-science

Вопрос:

В представлении «Создать» я пытаюсь перечислить некоторые вторичные/внешние данные модели. Вместо этого страница возвращает ошибку NullReferenceError, и я не могу понять, почему модель равна нулю. Если я отфильтрую значение IsNull по перечисляющим полям, которые являются нулевыми, страница загрузится.

Ниже приведены функции создания внутри контроллера:

 public IActionResult Create() {  return View(); }  [HttpPost] [ValidateAntiForgeryToken] public async Tasklt;IActionResultgt; Create([Bind("SOFT_ID,SOFT_NAME,DEPT_ID,IT_CONTACT,SOFT_EXP_DATE,SOFT_SUP_PERIOD,SOFT_OUT_OF_SERVICE,VEND_ID,SUPP_ID,SOFT_IS_RENEWED")] Software software) {  if (ModelState.IsValid)  {  _context.Add(software);  await _context.SaveChangesAsync();  return RedirectToAction(nameof(Index));  }  return View(); }  

Далее идут Модели. Ниже приведена модель программного обеспечения, которая является основной моделью, и модель отдела, которая является второстепенными моделями. Есть две другие модели, из которых я хочу загрузить данные, и обе они настроены точно так же, как модель отдела.

Модель программного обеспечения:

 public class Software {  [Key]  public int SOFT_ID { get; set; }  [Required]  [StringLength(50, ErrorMessage = "Software Name cannont be longer than 50 characters.")]  [Display(Name = "Software Name")]  public string SOFT_NAME { get; set; }  [Required]  public virtual Department DEPT_ID { get; set; }  [Required]  [Display(Name = "IT Contact")]  public string IT_CONTACT { get; set; }  [Required]  [Display(Name = "Expiration Date")]  [DataType(DataType.Date)]  public DateTime SOFT_EXP_DATE { get; set; }  [Required]  [Range(1,5)]  [Display(Name = "Support Period")]  public int SOFT_SUP_PERIOD { get; set; }  [Display(Name = "No Longer Used")]  public bool SOFT_OUT_OF_SERVICE { get; set; }  [Required]  public virtual Vendor VEND_ID { get; set; }  [Required]  public virtual Supplier SUPP_ID { get; set; }  [Display(Name = "Renewed?")]  public bool SOFT_IS_RENEWED { get; set; }    public IEnumerablelt;Departmentgt; Departments { get; set; }  public IEnumerablelt;Suppliergt; Suppliers { get; set; }  public IEnumerablelt;Vendorgt; Vendors { get; set; } }  

Модель отдела:

 public class Department {  [Key]  public int DEPT_ID { get; set; }  [Required]  [Display(Name = "Department Name")]  public string DEPT_NAME { get; set; }  [Required]  [Display(Name = "Department Contact Name")]  public string DEPT_CONTACT { get; set; }  [Required]  [Display(Name = "Email")]  public string DEPT_EMAIL { get; set; }  [Required]  [Display(Name = "Phone")]  public string DEPT_PHONE { get; set; } }   

And finally there is the View. The sections that are throwing the NullReferenceError are the @foreach loops for the departments, suppliers, and vendors. These are supposed to be populating drop down menus.

 @model SoftwareManager_SSO.Models.Software  @{  ViewData["Title"] = "Create"; }  lt;h1gt;Createlt;/h1gt;   lt;h4gt;Softwarelt;/h4gt; lt;hr /gt; lt;div class="row"gt;  lt;div class="col-md-4"gt;  lt;form asp-action="Create"gt;  lt;div asp-validation-summary="ModelOnly" class="text-danger"gt;lt;/divgt;  lt;div class="form-group"gt;  lt;label asp-for="SOFT_NAME" class="control-label"gt;lt;/labelgt;  lt;input asp-for="SOFT_NAME" class="form-control" /gt;  lt;span asp-validation-for="SOFT_NAME" class="text-danger"gt;lt;/spangt;  lt;/divgt;   lt;div class="form-group"gt;  lt;label asp-for="DEPT_ID.DEPT_NAME" class="control-label"gt;lt;/labelgt;  lt;select class="form-control"gt;  lt;option value="" disabled selectedgt;Select A Deptlt;/optiongt;  @foreach (var item in Model.Departments)  {  lt;option value="@item.DEPT_ID"gt;@item.DEPT_NAMElt;/optiongt;  }  lt;/selectgt;  lt;span asp-validation-for="DEPT_ID.DEPT_NAME"gt;lt;/spangt;  lt;/divgt;   lt;div hidden="hidden" class="form-group"gt;  lt;label asp-for="DEPT_ID" class="control-label"gt;lt;/labelgt;  lt;input asp-for="DEPT_ID" class="form-control" disabled="disabled" /gt;  lt;span asp-validation-for="DEPT_ID" class="text-danger"gt;lt;/spangt;  lt;/divgt;  lt;div class="form-group"gt;  lt;label asp-for="DEPT_ID.DEPT_CONTACT" class="control-label"gt;lt;/labelgt;  lt;input id="dept_contact" asp-for="DEPT_ID.DEPT_CONTACT" disabled="disabled" class="form-control" /gt;  lt;span asp-validation-for="DEPT_ID.DEPT_CONTACT" class="text-danger"gt;lt;/spangt;  lt;/divgt;  lt;div class="form-group"gt;  lt;label asp-for="IT_CONTACT" class="control-label"gt;lt;/labelgt;  lt;select class="form-control"gt;  lt;option value="" selectedgt;Select IT Personlt;/optiongt;  lt;option value="uciltas@tohowater.com"gt;Umit Ciltaslt;/optiongt;  lt;option value="sslaven@tohowater.com"gt;Stephen Slavenlt;/optiongt;  lt;option value="imoreno@tohowater.com"gt;Ismael Morenolt;/optiongt;  lt;option value="dkearney@tohowater.com"gt;David Kearneylt;/optiongt;  lt;/selectgt;  lt;span asp-validation-for="IT_CONTACT" class="text-danger"gt;lt;/spangt;  lt;/divgt;  lt;div class="form-group"gt;  lt;label asp-for="SOFT_EXP_DATE" class="control-label"gt;lt;/labelgt;  lt;input asp-for="SOFT_EXP_DATE" class="form-control" /gt;  lt;span asp-validation-for="SOFT_EXP_DATE" class="text-danger"gt;lt;/spangt;  lt;/divgt;  lt;div class="form-group"gt;  lt;label asp-for="SOFT_SUP_PERIOD" class="control-label"gt;lt;/labelgt;  lt;select class="form-control"gt;  lt;option value="" selectedgt;Select A Support Periodlt;/optiongt;  lt;option value="1"gt;1 Yearlt;/optiongt;  lt;option value="2"gt;2 Yearslt;/optiongt;  lt;option value="3"gt;3 Yearslt;/optiongt;  lt;option value="4"gt;4 Yearslt;/optiongt;  lt;option value="5"gt;5 Yearslt;/optiongt;  lt;/selectgt;  lt;span asp-validation-for="SOFT_SUP_PERIOD" class="text-danger"gt;lt;/spangt;  lt;/divgt;   lt;div class="form-group"gt;  lt;label asp-for="VEND_ID.VEND_NAME" class="control-label"gt;lt;/labelgt;  lt;select class="form-control"gt;  lt;option value="" disabled selectedgt;Select a Vendorlt;/optiongt;  @foreach (var item in Model.Vendors)  {  lt;option value="@item.VEND_ID"gt;@item.VEND_NAMElt;/optiongt;  }  lt;/selectgt;  lt;span asp-validation-for="VEND_ID.VEND_NAME"gt;lt;/spangt;  lt;/divgt;   lt;div class="form-group"gt;  lt;label asp-for="SUPP_ID.SUPP_NAME" class="control-label"gt;lt;/labelgt;  lt;select class="form-control"gt;  lt;option value="" disabled selectedgt;Select a Vendorlt;/optiongt;  @foreach (var item in Model.Suppliers)  {  lt;option value="@item.SUPP_ID"gt;@item.SUPP_NAMElt;/optiongt;  }  lt;/selectgt;  lt;span asp-validation-for="SUPP_ID.SUPP_NAME"gt;lt;/spangt;  lt;/divgt;   lt;div class="form-group form-check"gt;  lt;label class="form-check-label"gt;  lt;input class="form-check-input" asp-for="SOFT_IS_RENEWED" /gt; @Html.DisplayNameFor(model =gt; model.SOFT_IS_RENEWED)  lt;/labelgt;  lt;/divgt;  lt;div class="form-group form-check"gt;  lt;label class="form-check-label"gt;  lt;input class="form-check-input" asp-for="SOFT_OUT_OF_SERVICE" /gt; @Html.DisplayNameFor(model =gt; model.SOFT_OUT_OF_SERVICE)  lt;/labelgt;  lt;/divgt;  lt;div class="form-group"gt;  lt;input type="submit" value="Create" class="btn btn-primary" /gt;  lt;/divgt;  lt;/formgt;  lt;/divgt; lt;/divgt;  lt;divgt;  lt;a asp-action="Index"gt;Back to Listlt;/agt; lt;/divgt;  @section Scripts {  @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }  

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

Ответ №1:

Вам нужно передать информацию об этих отделах в представление. Обычно это делается путем создания модели представления и передачи ее в представление.

В вашем коде ваше представление ожидает модель «программного обеспечения», поэтому вы можете создать ее (и обязательно заполнить «отделы») и передать ее в свое представление.

Как только у вас будет модель, вы можете использовать Html-помощник для создания раскрывающегося списка, а не создавать его вручную с помощью цикла.

Например:

 @Html.DropDownListFor(model =gt; model.departments )   

Или, может быть,

 @Html.DropDownListFor(model =gt; model.departments as selectlist)  

Извините, если какой-то синтаксис не совсем правильный, на моем мобильном телефоне так что не могу проверить очень хорошо. Но это должно навести вас на правильную мысль.

Редактировать

Вам нужно построить модель представления в вашем контроллере и передать ее в представление.

 var viewModel = new Software(); viewModel.Departments = new Listlt;Departmentgt;() {  new Department() { DEPT_NAME = "Some department name"} }; return View(viewModel);  

Или при динамическом извлечении из базы данных (например, через entity framework):

 var viewModel = new Software(); viewModel.Departments = _db.Departments.ToList() return View(viewModel);  

Комментарии:

1. Будет ли это по-прежнему работать, если данные модели извлекаются из серверной части базы данных? Например, сегодня у меня может быть четыре отдела, но в будущем у меня может быть еще два дополнительных отдела. Таблица отдела, из которой он извлекается, не статична и в будущем может содержать больше данных, чем сейчас. Спасибо за ваше предложение, я посмотрю, смогу ли я вписать это в свою настройку.

2. Я попробовал следующее и все равно получил исключение NullReferenceException: Ссылка на объект не установлена на экземпляр объекта. @Html.DropDownListFor(Model =gt; Model.Departments, new SelectList(Model.Departments, "DEPT_ID", "DEPT_NAME"),"Select Department")) Это правильно?

3. Если вы не заполнили модель представления в контроллере, то вы всегда будете получать нулевую ссылку на модель. Отделы. Я обновлю ответ примером того, как создать модель и перейти к просмотру

4. Большое вам спасибо! Часть, которую вы отредактировали, о том, как вставить таблицы базы данных через ViewModel, сделала свое дело. Для тех, кто в будущем увидит это, я добавил этот код в начальную функцию Create (). После этого мои выпадающие списки заполняются строками в таблицах базы данных. Еще раз спасибо вам, Дин О’Брайен!

5. Добро пожаловать. Рад, что это сработало