Hello everybody. Faced a problem: in the application I need to add the product to the database, while it is not known in advance how many different descriptions (characteristics) it will have on this there are 2 tables - Products and Characteristics. When adding a new product, you must send to the server the product form and a collection of characteristics. I made a general model for this. But when I click submit and check the dev tools, there I see that the product model is being sent, and there are no close specifications. Where is my mistake? Below lay the listing of models, server code and view.
Product Model:
public partial class bs_parts { public bs_parts() { this.bs_details = new HashSet<bs_details>(); this.bs_images = new HashSet<bs_images>(); this.bs_orders = new HashSet<bs_orders>(); } public decimal parts_id { get; set; } public decimal parts_category_id { get; set; } public decimal parts_brand_id { get; set; } public string parts_model { get; set; } public double parts_price { get; set; } public int parts_amount { get; set; } public virtual bs_brands bs_brands { get; set; } public virtual bs_categories bs_categories { get; set; } public virtual ICollection<bs_details> bs_details { get; set; } public virtual ICollection<bs_images> bs_images { get; set; } public virtual ICollection<bs_orders> bs_orders { get; set; } } Feature Model:
public partial class bs_details { public decimal details_id { get; set; } public string details_name { get; set; } public string details_value { get; set; } public decimal details_part_id { get; set; } public virtual bs_parts bs_parts { get; set; } } And the general model:
public class AddPartViewModel { public bs_parts part { get; set; } public List<bs_details> detail { get; set; } public bs_images image { get; set; } } Server side code:
[HttpPost] public ActionResult CreatePart(AddPartViewModel model, HttpPostedFileBase uploadImage) { ViewBag.Categories = new SelectList(_db.bs_categories, "categories_id", "categories_name"); ViewBag.Brands = new SelectList(_db.bs_brands, "brands_id", "brands_name"); if (ModelState.IsValid && model.part != null) { model.part.parts_brand_id = 3; model.part.parts_category_id = 3; _db.bs_parts.Add(model.part); if (model.detail != null) { foreach (var details in model.detail) { details.details_part_id = 8; _db.bs_details.Add(details); _db.SaveChanges(); } } if (ModelState.IsValid && uploadImage!=null) { byte[] imageData = null; using (var binaryReader = new BinaryReader(uploadImage.InputStream)) { imageData = binaryReader.ReadBytes(uploadImage.ContentLength); } model.image.image_part_id = model.part.parts_id; model.image.images_image = imageData; _db.bs_images.Add(model.image); } //добавить else if () {...} если модель есть, а изображения нет _db.SaveChanges(); return RedirectToAction("Main"); } return View(model); } View:
<div> <p> Выбрать категорию: @Html.DropDownList("Categories"); </p> </div> <div> <p> Выбрать производителя: @Html.DropDownList("Brands"); </p> </div> <div> <p> Название модели: @Html.EditorFor(model=>model.part.parts_model) @Html.ValidationMessageFor(model=>model.part.parts_model) </p> </div> <div> <p> Цена: @Html.EditorFor(model=>model.part.parts_price) @Html.ValidationMessageFor(model=>model.part.parts_price) </p> </div> <div> <p> Количество: @Html.EditorFor(model=>model.part.parts_amount) @Html.ValidationMessageFor(model=>model.part.parts_amount) </p> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <form id="myForm" method="post" action="~/Controllers/AdminController.cs"> <div class="details"> <div class="details-part"> <input class="details_name" type="text" /> <input class="details_value" type="text" /> </div> </div> <div><p><a class="plus">Add detail</a></p></div> <div> <input type="file" name="uploadImage" /> </div> <input type="hidden" name="details"/> <div> <button id="save-form">Save</button> </div> </form> Script to send and add new fields:
<script> var $myForm = $("#myForm"); $(".plus").off("click").on("click", function () { $(".details").append('<div class="details-part"> <input class="details_name" type="text" /> <input class="details_value" type="text" /> </div>') }); $("#save-form").off("click").on("click", function () { var detailList = []; $myForm.find(".details-part").each(function () { detailList.push({ details_value: $(this).find(".details_value").val(), details_name: $(this).find(".details_name").val() }) }); $myForm.find('[name="details"]').val(JSON.stringify(detailList)) $myForm.submit() }); In this version, detail comes null, but if you change it and do it like this:
<input name="detail[0].details_name" type="text" /> <input name="detail[0].details_value" type="text" /> <input name="detail[1].details_name" type="text" /> <input name="detail[1].details_value" type="text" /> <input name="detail[2].details_name" type="text" /> <input name="detail[2].details_value" type="text" /> That comes to the server 3 detail objects and everything is ok. The problem will be, if I want to remove the object in the middle, then the order will be broken. I have already been told that you can not delete, but make the fields hidden, and on the server already do a check for an empty field. I am not in JS with a foot, maybe someone who has free time and a desire can help write a script such that it adds new fields and makes them hidden when "deleted". With the addition I can handle, but with the second problem.
AddPartViewModel- it is used on the view. And when you open the page, do you have adetailin the model accidentally notnull? - Denis Bubnov