Ошибка Microsoft.AspNetCore.Mvc.Razor.RazorPage.Model.get вернул null. во View
Есть Модель Product
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Range(1, int.MaxValue)]
public double Price { get; set; }
public string Image { get; set; }
[Display(Name = "Category Type")]
public int CategoryId { get; set; }
[ForeignKey("CategoryId")]
public virtual Category Category { get; set; }
}
Такой контроллер Product Controller с Index и методом Get Post для добавление и редактирования продукта
public IActionResult Index()
{
IEnumerable<Product> objList = _db.Product;
foreach (var obj in objList)
{
obj.Category = _db.Category.FirstOrDefault(u => u.Id == obj.CategoryId);
};
return View(objList);
}
//GET - UPSERT
public IActionResult Upsert(int? id)
{
//IEnumerable<SelectListItem> CategoryDropDown = _db.Category.Select(i => new SelectListItem
//{
// Text = i.Name,
// Value = i.Id.ToString()
//});
////ViewBag.CategoryDropDown = CategoryDropDown;
//ViewData["CategoryDropDown"] = CategoryDropDown;
//Product product = new Product();
ProductVM productVM = new ProductVM()
{
Product = new Product(),
CategorySelectList = _db.Category.Select(i => new SelectListItem
{
Text = i.Name,
Value = i.Id.ToString()
})
};
if (id == null)
{
//this is for create
return View(productVM);
}
else
{
productVM.Product = _db.Product.Find(id);
if (productVM.Product == null)
{
return NotFound();
}
return View(productVM);
}
}
//POST - UPSERT
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Upsert(ProductVM productVM)
{
if (ModelState.IsValid)
{
var files = HttpContext.Request.Form.Files;
string webRootPath = _webHostEnvironment.WebRootPath;
if (productVM.Product.Id == 0)
{
//Creating
string upload = webRootPath + WC.ImagePath;
string fileName = Guid.NewGuid().ToString();
string extension = Path.GetExtension(files[0].FileName);
using (var fileStream = new FileStream(Path.Combine(upload, fileName + extension), FileMode.Create))
{
files[0].CopyTo(fileStream);
}
productVM.Product.Image = fileName + extension;
_db.Product.Add(productVM.Product);
}
else
{
//updating
}
_db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
Когда отправляю заполненные поля в контроллер в самом начале View появляется такая ошибка: System.NullReferenceException: "Object reference not set to an instance of an object."
Microsoft.AspNetCore.Mvc.Razor.RazorPage.Model.get вернул null.
@model WebApp.Models.ViewModels.ProductVM
@{
var title = "Create Product";
}
<form method="post" enctype="multipart/form-data">
@if (Model.Product.Id != 0)
{
title = "Edit Product";
<input asp-for="Product.Id" hidden />
}
<div class="border p-3">
<div class="form-group row">
<h2 class="text-info pl-3">@title</h2>
</div>
<div class="row">
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="Product.Name"></label>
</div>
<div class="col-8">
<input asp-for="Product.Name" class="form-control" />
<span asp-validation-for="Product.Name" class="text-danger"></span>
</div>
Ответы (4 шт):
В Post обработчике вы получаете файлы из формы, попробуйте добавить аттрибут [FromForm], что бы обработчик получал модель из формы, а не из Body:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Upsert([FromForm] ProductVM productVM)
Так же на странице у вас нет проверки на Model.Product is null, поэтому в случае когда Model.Product == null у вас будет выдавать System.NullReferenceException, добавление проверки скорее всего исправит вашу ошибку
У вас в POST методе при невалидной модели возвращается просто View(), соответственно View не получает модель.
Напишите в конце POST метода вместоreturn View() следующее:
return View(productVM);
Решением проблемы оказалось удаление проверки модели на валидность
if (ModelState.IsValid) в controller, почему-то проверка не проходит модели, буду разбираться
ModelState.IsValid не проходит из-за того что некоторые свойства модели имеют не допустимое значение Null. Исправить можно так, добавив оператор "?":
public string? Image { get; set; }
Или отключить это поведение с помощью параметра в Program.cs
builder.Services.AddControllers(
options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);