I'm learning Asp.net Core and building a simple web with CRUD operations, SQL server and using Entity Framework.
when I try to add new products to test it I git this error I tried many things to solve it but nothing changed so I need to figure out what's the problem, I know its betweenthe actionResult Add and the Add view :
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'Microsoft.AspNetCore.Mvc.RedirectToActionResult', but this ViewDataDictionary instance requires a model item of type 'StockApp.Models.Product'.
that's my Product Model:
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore;
using System.ComponentModel.DataAnnotations;
using FluentValidation;
namespace StockApp.Models
{
[Table("Products", Schema = "dbo")]
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "Product ID")]
public int ProductId { get; set; }
[Required]
[Column(TypeName = "varchar(150)")]
[Display(Name = "Product Name")]
public string ProductName { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MMM/yyyy}")]
[Display(Name = "Prodution Date")]
public DateTime ProductionDate { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MMM/yyyy}")]
[Display(Name = "Expiration Date")]
public DateTime ExpirationDate { get; set; }
[Required]
[Column(TypeName = "decimal(12,2)")]
[Display(Name = "Price")]
public decimal Price { get; set; }
//Category model/table
[ForeignKey("Category")]
[Required]
public int CategoryId { get; set; }
[Display(Name = "Category")]
[NotMapped]
public string CategoryName { get; set; }
public virtual Category Category { get; set; }
Factory model/table
[ForeignKey("Factory")]
[Required]
public int FactoryId { get; set; }
[Display(Name = "Made By")]
[NotMapped]
public string FactoryName { get; set; }
public virtual Factory Factory { get; set; }
}
}
that's my ProductController:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using StockApp.Data;
using StockApp.Models;
using System.Linq;
namespace StockApp.Controllers
{
public class ProductController : Controller
{
private readonly StockDbContext _dbContext;
public ProductController(StockDbContext dbContext)
{
_dbContext = dbContext;
}
// GET: ProductController
public IActionResult Index()
{
//var productDbContext = _dbContext.Products.Include(e => e.Category) .Include(e => e.Factory);
//return View(productDbContext.ToList());
var productss = (from Product in _dbContext.Products
join Category in _dbContext.Categories on Product.ProductId equals Category.CategoryId
join Factory in _dbContext.Factories on Product.ProductId equals Factory.FactoryId
select new Product
{
ProductId = Product.ProductId,
ProductName = Product.ProductName,
ProductionDate = Product.ProductionDate,
ExpirationDate = Product.ExpirationDate,
CategoryId = Product.CategoryId,
CategoryName = Category.CategoryName,
FactoryId = Product.FactoryId,
FactoryName = Factory.FactoryName
}).ToList();
return View(productss);
}
// GET: ProductController/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: ProductController/Create
public IActionResult Add()
{
ViewBag.Category = this._dbContext.Categories.ToList();
ViewBag.Factory = this._dbContext.Factories.ToList();
return View();
}
// POST: ProductController/Create
[HttpPost]
public IActionResult Add(Product model)
{
ModelState.Remove("Category");
ModelState.Remove("CategoryName");
ModelState.Remove("Factory");
ModelState.Remove("FactoryName");
if (ModelState.IsValid)
{
_dbContext.Products.Add(model);
_dbContext.SaveChanges();
return View(RedirectToAction("Index"));
}
ViewBag.Category = _dbContext.Categories.ToList();
ViewBag.Factory = _dbContext.Factories.ToList();
return View("Add", model);
}
// GET: ProductController/Edit/5
public IActionResult Edit(int id)
{
return View();
}
// POST: ProductController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: ProductController/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: ProductController/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
}
}
Add View:
@model Product
@{
ViewBag.Title = "Add";
}
<h2>@ViewBag.Title Product</h2>
<h4>Product</h4>
<div >
<div >
<form [email protected]>
<div asp-validation-summary=All ></div>
<div >
<label asp-for="ProductName" ></label>
<input asp-for="ProductName" />
<span asp-validation-for="ProductName" ></span>
</div>
<div >
<label asp-for="ProductionDate" ></label>
<input asp-for="ProductionDate" />
<span asp-validation-for="ProductionDate" ></span>
</div>
<div >
<label asp-for="ExpirationDate" ></label>
<input asp-for="ExpirationDate" />
<span asp-validation-for="ExpirationDate" ></span>
</div>
<div >
<label asp-for="Price" ></label>
<input asp-for="Price" />
<span asp-validation-for="Price" ></span>
</div>
<div >
<label asp-for="CategoryId" ></label>
<select asp-for="CategoryId" asp-items="@(new SelectList(ViewBag.Category,"CategoryId","CategoryName"))" class ="form-control"></select>
</div>
<div >
<label asp-for="FactoryId" ></label>
<select asp-for="FactoryId" asp-items="@(new SelectList(ViewBag.Factory,"FactoryId","FactoryName"))" class ="form-control"></select>
</div>
<div >
<input type="submit" value="Create" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
index view :
@model IEnumerable<StockApp.Models.Product>
@{
ViewBag.Title = "Product";
}
<h1>All Productts</h1>
<p>
<a asp-action="Add" >Add New Product</a>
</p>
<table >
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.ProductName)
</th>
<th>
@Html.DisplayNameFor(model => model.ProductionDate)
</th>
<th>
@Html.DisplayNameFor(model => model.ExpirationDate)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th>
@Html.DisplayNameFor(model => model.CategoryName)
</th>
<th>
@Html.DisplayNameFor(model => model.FactoryName)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.ProductName)
</td>
<td>
@Html.DisplayFor(modelItem => item.ProductionDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.ExpirationDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.CategoryName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FactoryName)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ProductId">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ProductId">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ProductId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
CodePudding user response:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'Microsoft.AspNetCore.Mvc.RedirectToActionResult', but this ViewDataDictionary instance requires a model item of type 'StockApp.Models.Product'.
It is because you use return View(RedirectToAction("Index"));
in your action Create
.Try to use return RedirectToAction("Index");
to replace return View(RedirectToAction("Index"));
.