Ashiv3r
Ashiv3r

Reputation: 994

The key 'CategoryID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'

Got a little problem with saving my Product. Dropdownlist is getting populated, abut when I try to save I have an error which is stated in title. I read tons of articles about it, but any of it helped me out. What can affect my code? Any ideas?

Controller:

// GET: Admin/Products/Create
public ActionResult Create()
{
    string domain = Request.Url.Host;
    int clientid = (from a in db.Client where a.Domain == domain select a.ID).First();

    int maxID = db.Product.Where(c => c.ClientID == clientid).Max(c => (int?)c.ProductID) ?? 0;
    ViewBag.MaxID = maxID + 1;

    List<SelectListItem> categories = new List<SelectListItem>();
    foreach (var cat in db.Category.Where(c => c.ClientID == clientid))
    {
        categories.Add(new SelectListItem() { Text = cat.Name, Value = cat.CategoryID.ToString() });
    }

    ViewBag.Categories = categories;

        return View();
}

// POST: Admin/Products/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,ProductID,Name,CategoryID,Price,Promotion,Image1,Image2,Image3,Image4,Description,ClientID")] Product product, HttpPostedFileBase file1, HttpPostedFileBase file2, HttpPostedFileBase file3, HttpPostedFileBase file4)
{
    if (ModelState.IsValid)
    {
        if (file1 != null)
        {
            var fileName1 = Path.GetFileName(file1.FileName);
            var path1 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName1);
            file1.SaveAs(path1);

            @product.Image1 = Url.Content("~/Images/Products/" + fileName1);
        }

        if (file2 != null)
        {
            var fileName2 = Path.GetFileName(file2.FileName);
            var path2 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName2);
            file2.SaveAs(path2);

            @product.Image2 = Url.Content("~/Images/Products/" + fileName2);
        }

        if (file3 != null)
        {
            var fileName3 = Path.GetFileName(file3.FileName);
            var path3 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName3);
            file3.SaveAs(path3);

            @product.Image3 = Url.Content("~/Images/Products/" + fileName3);
        }

        if (file4 != null)
        {
            var fileName4 = Path.GetFileName(file4.FileName);
            var path4 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName4);
            file4.SaveAs(path4);

            @product.Image4 = Url.Content("~/Images/Products/" + fileName4);
        }

        string domain = Request.Url.Host;
        int clientid = (from a in db.Client where a.Domain == domain select a.ID).First();

        List<SelectListItem> categories = new List<SelectListItem>();
        foreach (var cat in db.Category.Where(c => c.ClientID == clientid))
        {
            categories.Add(new SelectListItem() { Text = cat.Name, Value = cat.CategoryID.ToString() });
        }

        ViewBag.Categories = categories;

        db.Product.Add(product);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(product);
}

Dropdownlist in View:

<div class="col-md-2">
    <div class="form-group">
        <label>Kategoria</label>
        @Html.DropDownListFor(model => model.CategoryID, (IEnumerable<SelectListItem>)ViewBag.Categories, new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
    </div>
</div>

Model:

public partial class Product
    {
        public int ID { get; set; }
        public int ProductID { get; set; }
        public string Name { get; set; }
        public int CategoryID { get; set; }
        public decimal Price { get; set; }
        public int Promotion { get; set; }
        public string Image1 { get; set; }
        public string Image2 { get; set; }
        public string Image3 { get; set; }
        public string Image4 { get; set; }
        [DataType(DataType.MultilineText)]
        [AllowHtml]
        public string Description { get; set; }
        public int ClientID { get; set; }
    }

Upvotes: 1

Views: 759

Answers (1)

JamieD77
JamieD77

Reputation: 13949

You're not setting the ViewBag.Categories in your post if ModelState is invalid.

Move your Select list code outside of the IsValid block

// POST: Admin/Products/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,ProductID,Name,CategoryID,Price,Promotion,Image1,Image2,Image3,Image4,Description,ClientID")] Product product, HttpPostedFileBase file1, HttpPostedFileBase file2, HttpPostedFileBase file3, HttpPostedFileBase file4)
{
    if (ModelState.IsValid)
    {
        if (file1 != null)
        {
            var fileName1 = Path.GetFileName(file1.FileName);
            var path1 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName1);
            file1.SaveAs(path1);

            @product.Image1 = Url.Content("~/Images/Products/" + fileName1);
        }

        if (file2 != null)
        {
            var fileName2 = Path.GetFileName(file2.FileName);
            var path2 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName2);
            file2.SaveAs(path2);

            @product.Image2 = Url.Content("~/Images/Products/" + fileName2);
        }

        if (file3 != null)
        {
            var fileName3 = Path.GetFileName(file3.FileName);
            var path3 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName3);
            file3.SaveAs(path3);

            @product.Image3 = Url.Content("~/Images/Products/" + fileName3);
        }

        if (file4 != null)
        {
            var fileName4 = Path.GetFileName(file4.FileName);
            var path4 = Path.Combine(Server.MapPath("~/Images/Products/"), fileName4);
            file4.SaveAs(path4);

            @product.Image4 = Url.Content("~/Images/Products/" + fileName4);
        }

        db.Product.Add(product);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    string domain = Request.Url.Host;
    int clientid = (from a in db.Client where a.Domain == domain select a.ID).First();

    List<SelectListItem> categories = new List<SelectListItem>();
    foreach (var cat in db.Category.Where(c => c.ClientID == clientid))
    {
        categories.Add(new SelectListItem() { Text = cat.Name, Value = cat.CategoryID.ToString() });
        } 
    ViewBag.Categories = categories;
    return View(product);
}

while you're at it.. Since you're also missing the MaxID value, you could just move the Viewbag code to a separate method so you just have to call the method before you return the view.

private void LoadCreateViewBagData()
{
    string domain = Request.Url.Host;
    int clientid = (from a in db.Client where a.Domain == domain select a.ID).First();
    int maxID = db.Product.Where(c => c.ClientID == clientid).Max(c => (int?)c.ProductID) ?? 0;

    ViewBag.MaxID = maxID + 1;

    List<SelectListItem> categories = new List<SelectListItem>();
    foreach (var cat in db.Category.Where(c => c.ClientID == clientid))
    {
        categories.Add(new SelectListItem() { Text = cat.Name, Value = cat.CategoryID.ToString() });
    }

    ViewBag.Categories = categories;
}

// GET: Admin/Products/Create
public ActionResult Create()
{
    LoadCreateViewBagData();
    return View();
}


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,ProductID,Name,CategoryID,Price,Promotion,Image1,Image2,Image3,Image4,Description,ClientID")] Product product, HttpPostedFileBase file1, HttpPostedFileBase file2, HttpPostedFileBase file3, HttpPostedFileBase file4)
{
    if (ModelState.IsValid)
    {
        //yada yada
    }
    LoadCreateViewBagData();
    return View(product);
}

Upvotes: 1

Related Questions