#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. Добро пожаловать. Рад, что это сработало