MVC Entity Framework Modifying Child Objects

I am new to MVC3 and EF4, and I am trying to implement the CRUD functions of a parent-child set of objects, however I have not found an example of some specific requirements that I need, and therefore would like a little help.

The situation I have is that I have a Product object that has child Category entities. I have all the CRUD functions that work perfectly for the Product object and the functionality of the parts that work with the Category object in the Product part view. However, I need to implement adding and removing a child Categories from a given Product .

Usually this will not be a problem, but in this case, when the user adds Category to the Product , I only need to allow the user to select from the list all available Categories from the database. The user will also be able to remove any of the existing child Categories from Product .

I expect that implementing DropDownList with all unused “categories” will work well, however I don’t know how to use it to allow the user to add and remove “Categories” and then save the changes to the database through EF.

Does anyone have any suggestions / examples on how to do this?

If any further information is required, please ask.

Thank you very much.

0
source share
1 answer

I did similar to authors and books with many relationships. The main idea is to create a JSON object from a view that contains all the authors inside it and is subordinate to the controller. I also used jQuery UI TagIt to allow the user to add / remove authors associated with the book. When the user clicks the Save Book button, the script builds a JSON object that mimics the Book object.

Below is the code. Make sure you add "json2.js" and "tagit.js" to the project before trying this code.

Browse Models:

  public class BookViewModel { public string Title { get; set; } public int BookId { get; set; } public int IsAvail { get; set; } public string CallNumber { get; set; } //Assiged authors public List<AuthorViewModel> Authors { get; set; } //available authors public List<AuthorViewModel> AuthorOptions { get; set; } } public class AuthorViewModel { public int AuthorId { get; set; } public string FirstName { get; set; } } 

Code for the book /Edit.chtml:

 @using System.Web.Script.Serialization @model eLibrary.Models.BookViewModel @{ ViewBag.Title = "Edit"; } <h2>Edit</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @*This is for JSON*@ <script src="../../Scripts/json2.js" type="text/javascript"></script> <script src="../../Scripts/tagit.js" type="text/javascript"></script> @*These are for styling Control*@ <link href="../../Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" /> <script type="text/javascript"> //This function is used for sending data(JSON Data) to BookController function BookSave() { // Step 1: Read View Data and Create JSON Object var author = { "AuthorId": "", "FirstName": "" }; // Creating book Json Object var book = { "BookId": "", "Title": "", "IsAvail": "", "CallNumber":"", "authors": []}; // Set Boook Value book.BookId = $("#BookId").val(); book.Title = $("#Title").val(); book.IsAvail = $("#IsAvail").val(); book.CallNumber = $("#CallNumber").val() ; var tags = $('#authors').tagit('tags'); for (var i in tags) { author.AuthorId = tags[i].value; author.FirstName = tags[i].label; book.authors.push(author ); author = { "AuthorId": "", "FirstName": "" }; } // Step 1: Ends Here // Set 2: Ajax Post // Here i have used ajax post for saving/updating information $.ajax({ url: '/Book/Edit', data: JSON.stringify(book), type: 'POST', contentType: 'application/json;', dataType: 'json', success: function (result) { if (result.Success == "1") { window.location.href = "/Book/Edit"; } else { alert(result.ex); } } }); } </script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Book Details</legend> @Html.HiddenFor(model => model.BookId) <div class="editor-label"> @Html.LabelFor(model => model.Title) </div> <div class="editor-field"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> <div class="editor-label"> @Html.LabelFor(model => model.IsAvail) </div> @Html.EditorFor(model => model.IsAvail) @Html.ValidationMessageFor(model => model.IsAvail) @Html.EditorFor(model => model.CallNumber); </fieldset> @Html.Partial("AuthorsByBook", Model.Authors, new ViewDataDictionary { { "mode", "EDIT" } }) <input type="button" value="Book Save" onclick="BookSave()" /> } 

Code for the book /AuthorsByBook.chtml

 @model IEnumerable< eLibrary.Models.AuthorViewModel> <link href="../../Content/tagit-awesome-blue.css" rel="stylesheet" type="text/css" /> <div class="box"> <ul id="authors" name="authors"> </ul> </div> <script type="text/javascript"> //Load authors in the javascript variable $(function () { var initialAuthorList=[]; @if(ViewData["mode"]=="EDIT") { foreach (var category in Model) { <text> initialAuthorList.push({label: "@category.FirstName", value: @category.AuthorId }); </text> } } $('#authors').tagit({tagSource: function (request, response) { $.ajax({ url: "/Author/SearchAuthor", type: "POST", dataType: "json", data: { searchText: request.term, maxResults: 10 }, success: function (data) { response($.map(data, function (item) { return { label: item.FirstName, value: item.AuthorId } })) } }) }, initialTags:initialAuthorList,minLength:3,allowNewTags:false,sortable:true,delay:400}); }); </script> 

Code for BookController.cs

 public ActionResult Edit(int id) { //To DO: use repository to fetch data Book book = db.Books.Single(a => a.BookId == id); Mapper.CreateMap<Book, BookViewModel>(); Mapper.CreateMap<Author, AuthorViewModel>(); BookViewModel bookVm = Mapper.Map<Book, BookViewModel>(book); List<AuthorViewModel> Authors = Mapper.Map<List<Author>,List<AuthorViewModel>>( db.Authors.ToList()); bookVm.AuthorOptions = Authors; return View(bookVm); } [HttpPost] public ActionResult Edit(BookViewModel bookv) { //create maps Mapper.CreateMap<AuthorViewModel, Author>(); Mapper.CreateMap<BookViewModel, Book>(); //convert view objects to model objects Book book = Mapper.Map<BookViewModel, Book>(bookv); List<Author> authors = Mapper.Map<List<AuthorViewModel>, List<Author>>(bookv.Authors.ToList()); //this has to be executed before db.Books.Attach //clear authors book.Authors.Clear(); db.Books.Attach(book); //assign authors to book foreach (Author a in authors) { db.Authors.Attach(a); } book.Authors.Clear(); foreach (Author a in authors) { book.Authors.Add(a); } db.ObjectStateManager.ChangeObjectState(book, EntityState.Modified); db.SaveChanges(); return RedirectToAction("Index"); } 

Code for the SearchAuthor method in AuthorController.cs

 public JsonResult SearchAuthor(string searchText, int? maxResults) { IEnumerable<Author> query = db.Authors; searchText = searchText.ToLower(); query = query.Where(c => c.FirstName.ToLower().Contains(searchText)); if ((maxResults ?? 0) == 0) { return Json(query.ToList()); } else { return Json(query.Take((int)maxResults).ToList()); } } 
0
source

Source: https://habr.com/ru/post/1433660/


All Articles