Good afternoon, when developing an MVC application, the following problem arose: there are production cards describing some products and materials from which this very product is created. The database has the following related tables:
Based on them, formed several models
Model TechnologicalCard describing the flow chart
namespace AccountingPlusProject.Models { using System; using System.Collections.Generic; public partial class TechnologicalCard { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public TechnologicalCard() { this.ReferenceMaterials = new HashSet<ReferenceMaterial>(); } public int IdTechnologicalCard { get; set; } public string NameProduct { get; set; } public string IdHeadDepartment { get; set; } public string Description { get; set; } public string Image { get; set; } public virtual AspNetUser AspNetUser { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection<ReferenceMaterial> ReferenceMaterials { get; set; } } } ReferenceMaterial model describing materials used in maps
namespace AccountingPlusProject.Models { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; public partial class ReferenceMaterial { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public ReferenceMaterial() { this.TechnologicalCards = new HashSet<TechnologicalCard>(); } public int IdMaterial { get; set; } public string NameMaterial { get; set; } public string Image { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public virtual ICollection<TechnologicalCard> TechnologicalCards { get; set; } public class CardEditModel { public TechnologicalCard Card { get; set; } public IEnumerable<ReferenceMaterial> Members { get; set; } public IEnumerable<ReferenceMaterial> NonMembers { get; set; } } public class CardModificationModel { public int[] IdsToAdd { get; set; } public int[] IdsToDelete { get; set; } } } } In TechnologicalCardController there is a GET method for adding materials to the map or removing materials from the map (based on two arrays of identifiers members and nonmembers, respectively)
public ActionResult EditMaterial(int id = 3) // передаваемый id карты = 3 только для теста { TechnologicalCard card = db.TechnologicalCards.FirstOrDefault(c => c.IdTechnologicalCard == id); int[] memberIDs = card.ReferenceMaterials.Select(m => m.IdMaterial).ToArray(); IEnumerable<ReferenceMaterial> members = db.ReferenceMaterials.Where(x => memberIDs.Any(y => y == x.IdMaterial)); IEnumerable<ReferenceMaterial> nonMembers = db.ReferenceMaterials.Except(members); return View(new CardEditModel { Card = card, Members = members, NonMembers = nonMembers }); } Code directly View
@using AccountingPlusProject.Models @model ReferenceMaterial.CardEditModel @{ ViewBag.Title = "Edit"; } <h2>-</h2> @Html.ValidationSummary() @using (Html.BeginForm()) { <input type="hidden" name="roleName" value="@Model.Card.IdTechnologicalCard" /> <div class="panel panel-primary"> <div class="panel-heading">Add to card<b>@Model.Card.IdTechnologicalCard</b></div> <table class="table table-striped"> @if (Model.NonMembers.Count() == 0) { <tr> <td colspan="2">!</td> </tr> } else { <tr> <td>Name</td> <td></td> </tr> foreach (ReferenceMaterial material in Model.NonMembers) { <tr> <td>@material.NameMaterial</td> <td> <input type="checkbox" name="IdsToAdd" value="@material.IdMaterial"> </td> </tr> } } </table> </div> <div class="panel panel-primary"> <div class="panel-heading">Delete from card<b>@Model.Card.IdTechnologicalCard</b></div> <table class="table table-striped"> @if (Model.Members.Count() == 0) { <tr> <td colspan="2">нету</td> </tr> } else { <tr> <td>Name</td> <td></td> </tr> foreach (ReferenceMaterial material in Model.Members) { <tr> <td>@material.NameMaterial</td> <td> <input type="checkbox" name="IdsToDelete" value="@material.IdMaterial"> </td> </tr> } } </table> </div> <button type="submit" class="btn btn-primary">Save</button> @Html.ActionLink("Cancel", "Index", null, new { @class = "btn btn-default" }) } This is how the presentation looks in the browser.
The selected checkbox is passed to IdsToDelete or IdsToAdd, according to which materials will be deleted or added to the SelectedMaterial table, but I don’t know how to do this in the POST version of the EditMaterial method, help me figure it out. How to pull out the values understood, but how to insert or delete is still a mystery.
He himself thought to do something similar, but too drafted
[HttpPost] public ActionResult EditMaterial(CardModificationModel model) { if (ModelState.IsValid) { TechnologicalCard card = db.TechnologicalCards.Where(c => c.IdTechnologicalCard == 3).FirstOrDefault(); foreach (int materialId in model.IdsToAdd ?? new int[] { }) { ReferenceMaterial material = db.ReferenceMaterials.Where(m => m.IdMaterial == materialId).First(); card.ReferenceMaterials.Add(material); db.SaveChanges(); } foreach (int materialId in model.IdsToDelete ?? new int[] { }) { ReferenceMaterial material = db.ReferenceMaterials.Where(m => m.IdMaterial == materialId).First(); card.ReferenceMaterials.Remove(material); } return RedirectToAction("Index"); } return View("Error", new string[] { "Роль не найдена" }); } 
