I have a working MVC 5 app we use for classroom supplies with a simple welcome page that shows all categories along the left side of the page and a partial view that displays all subcategories for any category that is clicked.
Click any subcategory and the view updates with all products that match the subcategory.
It's worked fine for quite some time but now I need to add a third nested subcategory so my subcategories can have a subcategory nested below it like this:
(1)Category (2)---Subcategory (3)------Subcategory
or
(1)Art Supplies (catgory) (2)---Crayons (subcategory) (2)---Paper (subcategory) (3)------Construction (sub-subcategory) (3)------Plain (sub-subcategory) (3)------Etching (sub subcategory)
I can't get my models updated correctly to produce what I need. I can't work out the proper way to add that third nested subcateory to our models. I've spent a few days trying and just can't determine the correct way to do it.
I've tried a "flat" single model with parentID, Parent Category, but can't get the create and edit pages to display drop-downs like our models below produce.
Being able to utilize drop-down menus on our create and edit pages are a plus as we have young students who use the app and it's simpler for them.
And I'd like to use the same to update our public view.
I know if I get the models correct then I can translate that to my views as needed. If anyone can help with the proper structure it would be very much appreciated.
Below are our models:
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<SubCategory> SubCategories { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class SubCategory
{
public int SubCategoryId { get; set; }
public string SubCategoryName { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class Product
{
[HiddenInput(DisplayValue = false)]
public int ProductId { get; set; }
public string ProductName { get; set; }
public int ProductNumber { get; set; }
public string UnitOfMeasure { get; set; }
public string ProductDescription { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public int SubCategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual SubCategory SubCategory { get; set; }
}
Here is our controller for our create action:
public class ProductsController : Controller
{
private EFDbContext db = new EFDbContext();
public ActionResult Create()
{
var catid = 1;
try
{
catid = (from c in db.Categories select c).FirstOrDefault().CategoryId;
}
catch (Exception)
{
catid = 1;
}
ViewBag.CategoryId = new SelectList(db.Categories, "CategoryId", "CategoryName", catid);
var subcategories = (from sub in db.SubCategories where sub.CategoryId == catid select new { sub.SubCategoryId, sub.SubCategoryName }).ToList();
ViewBag.SubCategoryId = new SelectList(subcategories, "SubCategoryId", "SubCategoryName");
return View();
}
// POST: Products/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ProductId,ProductName,ProductNumber,UnitOfMeasure,ProductDescription,Price,CategoryId,SubCategoryId")] Product product)
{
var subcatcheck = (from sub in db.SubCategories where sub.CategoryId == product.CategoryId && sub.SubCategoryId == product.SubCategoryId select new { sub.SubCategoryId, sub.SubCategoryName }).ToList();
if (ModelState.IsValid && product.ProductName != null && product.CategoryId != 0 && product.SubCategoryId != 0 && subcatcheck.Count != 0)
{
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CategoryId = new SelectList(db.Categories, "CategoryId", "CategoryName", product.CategoryId);
//ViewBag.SubCategoryId = new SelectList(db.SubCategories, "SubCategoryId", "SubCategoryName", product.SubCategoryId);
var subcategories = (from sub in db.SubCategories where sub.CategoryId == product.CategoryId select new { sub.SubCategoryId, sub.SubCategoryName }).ToList();
ViewBag.SubCategoryId = new SelectList(subcategories, "SubCategoryId", "SubCategoryName");
return View(product);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
And lastly our create view
#model 3rd6thgrade.Domain.Entities.Product
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ProductName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProductNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UnitOfMeasure, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UnitOfMeasure, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UnitOfMeasure, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProductDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductDescription, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductDescription, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Price, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Price, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CategoryId, "CategoryId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.DropDownList("CategoryId", null, htmlAttributes: new { #class = "form-control" })*#
#Html.DropDownList("CategoryId", null, new {onchange = "this.form.submit(0)", #class = "form-control"})
#Html.ValidationMessageFor(model => model.CategoryId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SubCategoryId, "SubCategoryId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("SubCategoryId", null, htmlAttributes: new { #class = "form-control" })
#* #Html.DropDownList("SubCategoryId", null, new { onchange = "this.form.submit(0)", #class = "form-control" })*#
#Html.ValidationMessageFor(model => model.SubCategoryId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Related
when i tried to submit my edit form i get this issue and i don't know why
productsController edit get
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//ProductsModel productsModel = await db.ProductsModels.FindAsync(id);
var products = await db.ProductsModels.Include(a =>a.categorieId).Include(a => a.users).FirstAsync(a => a.id == id);
if (products == null)
{
return HttpNotFound();
}
var selectedOwnerId = products.users?.Id ?? string.Empty;
var users = db.Users.Select(userItem => new SelectListItem
{
Text = userItem.Email,
Value = userItem.Id,
Selected = userItem.Id == selectedOwnerId
}).ToSafeReadOnlyCollection();
var selectedCategoryId = products.categorieId.id;
var productCategories = db.ProductCategoriesModels
.Select(a => new SelectListItem
{
Value = a.id.ToString(),
Text = a.name,
Selected = a.id == selectedCategoryId
}).ToSafeReadOnlyCollection();
var viewmodel = new productCreatEditViewModel()
{
Products = products,
productCategories = productCategories,
users = users
};
//ViewBag.users = userList;
//ViewBag.productcategorieId = new SelectList(db.ProductCategoriesModels, "id", "Name", productsModel.productcategorieId);
return View(viewmodel);
}
productsController edit post
// POST: Products/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "id,name,calorie,price,productcategorieId,userId")] ProductsModel productsModel)
{
if (ModelState.IsValid)
{
db.Entry(productsModel).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.productcategorieId = new SelectList(db.ProductCategoriesModels, "id", "Name", productsModel.productcategorieId);
return View(productsModel);
}
edit view
#model koelkast.ViewModels.productCreatEditViewModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ProductsModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Products.id)
<div class="form-group">
#Html.LabelFor(model => model.Products.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Products.name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Products.name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Products.calorie, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Products.calorie, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Products.calorie, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Products.price, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Products.price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Products.price, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Products.categorieId.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => Model.Products.categorieId.id,Model.productCategories, new { Name = "productCategoriesId", #class ="form-control"})
#Html.ValidationMessageFor(model => model.productCategories, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Products.users.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => Model.Products.users.Id,Model.users, new {Name = "UserId", #class = "form-control" })
#Html.ValidationMessageFor(model => model.Products.users.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
ViewModel
The model item passed into the dictionary is of type 'koelkast.Models.ProductsModel', but this dictionary requires a model item of type 'koelkast.ViewModels.productCreatEditViewModel'.
namespace koelkast.ViewModels
{
public class productCreatEditViewModel
{
[Required]
public ProductsModel Products { get; set; }
[Required]
public ICollection<SelectListItem> productCategories { get; set; }
[Required]
public ICollection<SelectListItem> users { get; set; }
}
}
productModel
namespace koelkast.Models
{
public class ProductsModel
{
[Key]
public int id { get; set; }
[Required,Display(Name = "name")]
public string name { get; set; }
//display name is de naam die hij gaat laten zien als nnaam in je view
[Required, Display(Name = "calorie")]
public int calorie { get; set; }
[Required, Display(Name = "price")]
public float price { get; set; }
[Display(Name = "categories")]
//hier zet je die foreing key
//zoals je kunt zien roep ik alleen de model aan
public int? productcategorieId { get; set; }
[ForeignKey("productcategorieId")]
public virtual ProductCategoriesModel categorieId { get; set; }
//je zegt hier dus dat dit de Id is(userId)
//van applicationUser table users
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser users { get; set; }
}
}
https://i.stack.imgur.com/Qaq67.png
you have a bug here, fix it
public async Task<ActionResult> Edit(ProductsModel productsModel)
{
}
you have 2 choices
1.Change ProductsModel to ProductCreatEditViewModel
or
Return ProductCreatEditViewModel as model
var viewmodel = new productCreatEditViewModel()
{
Products = productsModel,
productCategories = productCategories,
users = users
};
return View(viewModel);
I am trying to create a golf score app. I have created the database that has the following tables Round, Course and Hole.
The hole table has a foreign key to the courseId as when I create each hole I want to link it to a course.
When clicking on the create new I would like to have a dropdown list to select the courseId from when inputting all the hole details.
But when I click on the create new I get the following error in the Hole view model.
System.ArguementNullException: Value can not be Null. Parameter name items. in my Create action code within the HoleViewModelController.
This is my HoleViewModel code
public class HoleViewModel
{
[Key]
public int HoleId { get; set; }
public int HoleNumber { get; set; }
public int Par { get; set; }
public int Length { get; set; }
public int StrokeIndex { get; set; }
[ForeignKey("Course")]
public int? CourseId { get; set; }
public IEnumerable<SelectListItem> CourseNamesDropdownList { get; set; }
public virtual CourseViewModel Course { get; set; }
}
}
This is my CourseViewModel code
public class CourseViewModel
{
[Key]
public int CourseId { get; set; }
public string CourseName { get; set; }
This is my HoleViewModelController Create action
public ActionResult Create()
{
ViewBag.CourseId = new SelectList(db.CourseViewModels, "CourseId", "CourseName");
return View();
}
This is my MVC Create view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>HoleViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.HoleNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.HoleNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.HoleNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Par, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Par, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Par, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Length, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Length, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Length, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StrokeIndex, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StrokeIndex, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.StrokeIndex, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CourseId, "CourseId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Course.CourseId, Model.CourseNamesDropdownList, "Please select from List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
Ok so i resolved this issue by ammending the ActionResult Create code from
public ActionResult Create()
{
ViewBag.CourseId = new SelectList(db.CourseViewModels, "CourseId", "CourseName");
return View();
}
To
public ActionResult Create()
{
var dbcourse = db.Course.ToList();
//Make selectlist, which is IEnumerable<SelectListItem>
var courseNameDropdownList = new SelectList(db.Course.Select(item => new SelectListItem()
{
Text = item.CourseName.ToString(),
Value = item.CourseId.ToString()
}).ToList(), "Value", "Text");
// Assign the Selectlist to the View Model
var viewCourse = new HoleViewModel()
{
Course = dbcourse.FirstOrDefault(),
// The Dropdownlist values
CourseNamesDropdownList = courseNameDropdownList,
};
//ViewBag.CourseId = new SelectList(db.CourseViewModels, "CourseId", "CourseName");
return View(viewCourse);
}
This has allowed the dropdown to be populated and be added to the view.
I have been trying to come up with a solution for quite some time now but they all seem to fail.
I have two tables -> AssignedRoles & Incidence. Within the "Assignedroles" there is a "Status" Column that is auto-assigned "A" upon creation of data.
Given the nature of my program, i would like to change this value from "A" to "C" but from the "Incidence" Controller on the Edit Method.
Below is what i have tried.
public async Task<ActionResult> Edit(Incidence incidence, AssignedRoles assignedRoles)
{
if (ModelState.IsValid)
{
assignedRoles.Status = "C";
DB.Entry(incidence).State = EntityState.Modified;
DB.AssignedRoles.Add(assignedRoles);
UpdateModel(assignedRoles);
await DB.SaveChangesAsync();
return RedirectToAction("Dashboard");
}
return View(incidence);
}
The View Controller below displays Incidences allocated to the specific admin
The Members() contains the View from LoadUsersData()
public ActionResult Members()
{
return View();
}
public ActionResult LoadUsersData()
{
try
{
var draw = Request.Form.GetValues("draw").FirstOrDefault();
var start = Request.Form.GetValues("start").FirstOrDefault();
var length = Request.Form.GetValues("length").FirstOrDefault();
var sortColumn = Request.Form.GetValues("columns[" + Request.Form.GetValues("order[0][column]").FirstOrDefault() + "][name]").FirstOrDefault();
var sortColumnDir = Request.Form.GetValues("order[0][dir]").FirstOrDefault();
var searchValue = Request.Form.GetValues("search[value]").FirstOrDefault();
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int recordsTotal = 0;
var adminUserID = Convert.ToInt32(Session["AdminUser"]);
var rolesData = _IUsers.ShowallUsersUnderAdmin(sortColumn, sortColumnDir, searchValue, adminUserID);
recordsTotal = rolesData.Count();
var data = rolesData.Skip(skip).Take(pageSize).ToList();
return Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal, data = data });
}
catch (Exception)
{
throw;
}
}
The Edit Controller
[HttpGet]
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Incidence incidence = await DB.Incidences.FindAsync(id);
if (incidence == null)
{
return HttpNotFound();
}
return View(incidence);
}
Incidence Model
public class Incidence
{
[Key]
public int RegistrationID { get; set; }
[Required]
public string Name { get; set; }
[Required]
[MaxLength(7)]
public string TSCNO { get; set; }
public string General { get; set; }
public string Location { get; set; }
[Required]
[DataType(DataType.PhoneNumber)]
public string Cell { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.MultilineText)]
public string Issue { get; set; }
public int? RoleID { get; set; }
[DataType(DataType.MultilineText)]
[MinLength(5,ErrorMessage ="Provide Valid Feedback")]
public string FeedBack { get; set; }
}
AssignedRoles Model
public class AssignedRoles
{
[Key]
public int AssignedRolesID { get; set; }
public int? AssignToAdmin { get; set; }
public int? CreatedBy { get; set; }
public DateTime? CreatedOn { get; set; }
public int RegistrationID { get; set; }
public string Status { get; set; }
}
Incidence Edit View
#model CallCentre.Models.Incidence
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/AdminLTE.cshtml";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.RegistrationID)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TSCNO, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TSCNO, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TSCNO, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.General, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.General, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.General, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Location, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Location, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Location, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Cell, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Cell, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Cell, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Issue, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Issue, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Issue, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FeedBack, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FeedBack, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FeedBack, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
Modify your edit action to the code below.
// remove assignedRoles object on the parameter, we only need incidence
public async Task<ActionResult> Edit(Incidence incidence)
{
if (ModelState.IsValid)
{
// we need to select the assignedRole from that RegistrationId
var role = db.AssignedRoles.FirstOrDefault(a=>a.RegistrationID == incidence.RegistrationID)
role.Status = "C";
DB.Entry(incidence).State = EntityState.Modified;
// you're just editing the assignedRole right? no need to add a new one. Comment out or remove the code below
// DB.AssignedRoles.Add(assignedRoles);
// UpdateModel(assignedRoles);
await DB.SaveChangesAsync();
return RedirectToAction("Dashboard");
}
return View(incidence);
}
This question already has answers here:
What Causes The INSERT statement conflicted with the FOREIGN KEY constraint?
(2 answers)
Closed 6 years ago.
I'm working in ASP.NET MVC Web Application, so I want to insert values from another table (I get it with dropdownlist), but when I try to post, I get this:
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Products_dbo.Subcategories_SubcategoryId". The conflict
occurred in database "ProyectName", table "dbo.Subcategories", column
'SubcategoryId'. The statement has been terminated.
Products model:
public class Product
{
public int ProductId { get; set; }
public int SubcategoryId { get; set; }
public virtual Subcategory Subcategory { get; set; }
public string Name { get; set; }
public string Presentation { get; set; }
public string Image { get; set; }
public string Alt { get; set; }
public bool IsDeleted { get; set; }
Product ViewModel
public class ProductViewModel
{
public string Name { get; set; }
public string Presentation { get; set; }
public string Image { get; set; }
public string Alt { get; set; }
public int SelectedSubcategory { get; set; }
public IEnumerable <SelectListItem> Subcategory { get; set; }
}
Subcategory Model:
public class Subcategory
{
public int SubcategoryId { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public string Alt { get; set; }
public string Pdf { get; set; }
public bool IsDeleted { get; set; }
public bool IsInstalled { get; set; }
}
Get Controller
public ActionResult Create()
{
var subcategoryList = new ProductViewModel
{
Subcategory = new SelectList(db.SubcategoriesList, "SubcategoryId", "Name")
};
return View(subcategoryList);
}
Post Controller(Service method):
public class ProductService : IProductService
{
private EfDatabase db = new EfDatabase();
public async Task<string> CreateProduct(ProductViewModel model)
{
var product = new Product
{
Name = model.Name,
Presentation = model.Presentation,
Image = model.Image,
Alt = model.Alt,
SubcategoryId = model.SelectedSubcategory,
IsDeleted = false
};
db.ProductsList.Add(product);
await db.SaveChangesAsync();
return "Product " + model.Name + "has been created";
View:
#model Proyect.Models.ViewModels.ProductViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.SubcategoryId, "SubcategoryId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedSubcategory, Model.Subcategory, "-Selecciona una opcion-", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SelectedSubcategory)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Presentation, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Presentation, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Presentation, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Image, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Image, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Image, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Alt, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Alt, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Alt, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
So I don't found any error on my code, what's wrong with that? can any one help me to solve this problem?
My question is unique because model.SelectedSubcategory don't get Id value from another table, It always get 0 so in the other questions no make any comparision with that
Thankyou in advance!
MY CREATE VIEW NOW
#model myPROYECT.Models.ViewModels.ProductViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedSubcategory, Model.Subcategory, "-Selecciona una opcion-", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SelectedSubcategory)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Presentation, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Presentation, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Presentation, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Image, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Image, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Image, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Alt, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Alt, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Alt, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
There's nothing that requires a Subcategory to be selected. You're likely to get this error when a selection hasn't been made for subcategory. You should make subcategory required or make null a value that's possible to get back.
public class Product
{
public int ProductId { get; set; }
public int? SubcategoryId { get; set; }
public virtual Subcategory Subcategory { get; set; }
public string Name { get; set; }
public string Presentation { get; set; }
public string Image { get; set; }
public string Alt { get; set; }
public bool IsDeleted { get; set; }
}
using System.ComponentModel.DataAnnotations;
public class ProductViewModel
{
public int? SubcategoryId { get; set; }
public string Name { get; set; }
public string Presentation { get; set; }
public string Image { get; set; }
public string Alt { get; set; }
[Required]
public int? SelectedSubcategory { get; set; }
public IEnumerable Subcategory { get; set; }
}
Post Controller(Service method):
public class ProductService : IProductService
{
private EfDatabase db = new EfDatabase();
public async Task<string> CreateProduct(ProductViewModel model)
{
if (!ModelState.IsValid)
return View("Create");
var product = new Product
{
Name = model.Name,
Presentation = model.Presentation,
Image = model.Image,
Alt = model.Alt,
SubcategoryId = model.SelectedSubcategory,
IsDeleted = false
};
db.ProductsList.Add(product);
await db.SaveChangesAsync();
return "Product " + model.Name + "has been created";
}
}
Hey guys i need your help, i have a create employee form in MVC. I fill the form and select from the dropdown list and when i click submit, every other field returns a value except for the dropdown. i can't seem to fix the problem. this is what the form looks like.
this is the CreateEmployee Model
public class CreateEmployee
{
public int Id { get; set; }
public string FullName { get; set; }
[Required]
public string Notes { get; set; }
public int Department { get; set; }
public IEnumerable<AngTestDepartment> Departments { get; set; }
public bool PerkCar { get; set; }
public bool PerkStock { get; set; }
public bool PerkSixWeeks { get; set; }
public string PayrollType { get; set; }
}
the action controller
public ActionResult Employee(){
using (var db = new DepartmentDbContext())
{
var model = new CreateEmployee();
model.Departments = db.AngTestDepartments.ToList();
return View(model);
} }
and the view
#using (Html.BeginForm("CreateEmployee", "Employee", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Employee</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.FullName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FullName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FullName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Notes, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Notes, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Notes, "", new { #class = "text-danger" })
</div>
</div>
// the drop down doesnt return a value on submit
<div class="form-group">
#Html.LabelFor(model => model.Department, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.Departments,
Model.Departments.Select(d => new SelectListItem()
{
Value = d.id.ToString(),
Text = d.Department
}
), new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Department, "", new { #class = "text-danger" })
</div>
</div> }
and the action result called on submit
public ActionResult CreateEmployee(CreateEmployee newEmployee)
{
DbEmployeeTable.DbEmployeeTable_EmployeeTable(newEmployee);
return RedirectToAction("Employees");
}
thank you very much for your help.
Change the dropdownlist code to:
#Html.DropDownListFor(m => m.Department, new SelectList(Model.Departments.Select(d => new SelectListItem()
{
Value = d.id.ToString(),
Text = d.Department
}
)), new { htmlAttributes = new { #class = "form-control" } })
Dropdownlistfor's first argument should be the value that you're trying to get, and having the second be a select list will save you persistence-related headaches later.
As an aside, I'd also make the Model.Departments.Select result a model property so you don't clutter your view so much, but that's just a style concern.
Instead of
#Html.DropDownListFor(m => m.Departments,
try this...
#Html.DropDownListFor(m => m.Department,
That should return the department Id as an int from the selected value.