Model:
public class Category
{
[Key]
public int ID { get; set; }
[Required(ErrorMessage = "Kategoria jest wymagana!")]
public string Kategoria { get; set; }
[Required(ErrorMessage = "Kod jest wymagany!")]
public string Kod { get; set; }
}
Controller:
public ActionResult DodajPrzedmiot()
{
if (StaticFunctions.IfLogged())
{
using (var db = new DatabaseContext())
{
var cats = from b in db.Categories
select new { b.Kategoria };
var x = cats.ToList().Select(c => new SelectListItem
{
Text = c.Kategoria,
Value = c.Kategoria
}).ToList();
//List<SelectListItem> catList = new List<SelectListItem>();
//foreach (var t in cats)
//{
// SelectListItem s = new SelectListItem();
// s.Text = t.ToString();
// s.Value = t.ToString();
// catList.Add(s);
//}
ViewBag.Kategoria = x;
}
return View();
}
else
{
return RedirectToAction("Logowanie", "User");
}
}
View:
<div class="form-group">
@Html.LabelFor(model => model.Kategoria, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Kategoria, null)
</div>
</div>
The problem is that this list shows values that I selected from database, when I add an item with selected e.g. "Biurowe" category it adds informations to database but in the same time it gives me error:
An exception of type 'System.InvalidOperationException' occurred in System.Web.Mvc.dll but was not handled in user code
Additional information: There is no ViewData item of type 'IEnumerable' that has the key 'Kategoria'.
What should I change here?
The second parameter in @Html.DropDownListFor(model => model.Kategoria, null)
should be the list of items which would be ViewBag.Kategoria
in your case.
I would even suggest that you use a different name like ViewBag.KategoriaList
. I've run into problems sometimes when using the same name for list in ViewBag as that of the property being bound to DropDownList.
Try this code:
public ActionResult DodajPrzedmiot()
{
if (StaticFunctions.IfLogged())
{
using (var db = new DatabaseContext())
{
var cats = from b in db.Categories
select new { b.Kategoria };
var x = cats.ToList().Select(c => new SelectListItem
{
Text = c.Kategoria,
Value = c.Kategoria
}).ToList();
ViewBag.KategoriaList = x;
}
return View();
}
else
{
return RedirectToAction("Logowanie", "User");
}
}
In the View:
<div class="form-group">
@Html.LabelFor(model => model.Kategoria, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Kategoria, ViewBag.KategoriaList as IEnumerable<SelectListItem>)
</div>
</div>
You have to also populate the ViewBag
in POST
action. This is what your POST
action should be:
[HttpPost]
public ActionResult DodajPrzedmiot(Item itm)
{
if (ModelState.IsValid)
{
try
{
using (var db = new DatabaseContext())
{
// try putting this code in a separate function and use that function in both actions to populate the ViewBag.
var cats = from b in db.Categories
select new { b.Kategoria };
var x = cats.ToList().Select(c => new SelectListItem
{
Text = c.Kategoria,
Value = c.Kategoria
}).ToList();
ViewBag.KategoriaList = x;
if (itm.Ilosc_zakupiona - itm.Ilosc_wypozyczona < 0) throw new ArgumentOutOfRangeException();
itm.Ilosc_magazynowa = itm.Ilosc_zakupiona - itm.Ilosc_wypozyczona;
db.Items.Add(itm);
db.SaveChanges();
}
}
catch (System.Data.Entity.Infrastructure.DbUpdateException)
{
ViewBag.ErrorMessage = "Istnieje już przedmiot o takiej nazwie i/lub kodzie!";
return View();
}
catch (ArgumentOutOfRangeException)
{
ViewBag.ErrorMessage = "Ilość zakupiona i/lub wypożyczona nie mogą być mniejsze od zera!";
return View();
}
}
return View();
}