How to Insert to Master-detail tables in ASP.NET MVC 5

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-13 18:08:23

问题


I have Orders table and OrderDetails table in DB. With Entity Framework 6 I have obtained a model so I have classes generated from it. I also generated controllers and views from the Orders table.

Orders
folio (PK)
date
customer (FK)

OrdersDetail
folio (FK) -- to the Orders table
product (FK)
price
quantity 

The generated Create Post action is the following:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "folio,date,customer")] Orders order)
        {

            if (ModelState.IsValid)
            {
                db.Orders.Add(order);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.cliente = new SelectList(db.CATCTES, "COD_CTE", "NOM_CTE", order.cliente);

            return View(order);
        }

That's okay, but I would need to Insert to the other entity/table too! I already changed the Create.cshtml form, with the fields required for Orders table and including some kind of grid for OrdersDetail. Each row is a new entry for OrdersDetail table.

The problem, is I don't know how to properly save to the other table in the Create action at Orders controller. If this is not the right approach, tell me your comments.

Another concern is about POSTing, How should I name the inputs to be properly grouped and use submitted values at controller? Each row is generated by this script when I click a "+" button on the form:

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script>
        function add_row() {
            var detalle = $('#detalle');
            var newRow = '<tr>' + 
                            '<td data-title="Product">' +
                              '<div class="input-group">' +
                                '<span class="input-group-addon"></span>' +
                                  '<input class="form-control" type="number" aria-label="Product" name="detail_array[].product" step="0.001" min="0.000" onchange="cambiar_importe(this)" required="true">' +
                              '</div>' +
                            '</td>' +
                            '<td data-title="Price" >' +
                              '<div class="input-group">' +
                                '<span class="input-group-addon">$</span>' +
                                  '<input type="number" class="form-control" aria-label="Price" name="detail_array[].price" onchange="cambiar_importe(this)" step="0.001" min="0.000" required="true">' +
                              '</div>' +
                            '</td>' +
                            '<td data-title="Quantity">' +
                              '<div class="input-group">' +
                                '<span class="input-group-addon">$</span>' +
                                  '<input type="text" class="importe form-control" aria-label="Quantity" name="detail_array[].quantity" step="0.001" min="0.000" readonly="true" >' +
                              '</div>' +
                            '</td>' +
                            '<td data-title=""><button type="button" class="btn btn-danger btn-sm" onclick="borrar_renglon(this)">Cancelar</button></td>' +
                          '</tr>';

            detalle.append(newRow);
        }

    </script>
}

回答1:


I think you should use Ajax.

In your view you have the grid section, each time you add a record you have to post the values to the server using Ajax post form:

@using (Ajax.BeginForm("AddDetails", new AjaxOptions { UpdateTargetId = "gridContainerElementId" }))
{
  @Html.HiddenFor(m => m.folio)
  @Html.HiddenFor(m => m.product)
  @Html.TextBox(m => m.price)
  @Html.TextBox(m => m.quantity)
  <input type = "submit" value = "Save"/>
}

Note: put your grid in 'gridContainerElementId' div like:

<div id="gridContainerElementId">
  @Html.Action("DetailsGridPartial", new { OrderId = Model.folio })
</div>

In your controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddDetails(OrdersDetail orderDetails)
{
   if (ModelState.IsValid)
   {
      db.OrdersDetail.Add(orderDetails);
      db.SaveChanges();

      return RedirectToAction("DetailsGridPartial", new { OrderId =  orderDetails.folio });
   }
   return View(order);
}

public ActionResult DetailsGridPartial(int OrderId)
{
      var orderDetails = db.OrdersDetail.Where(w => w.folio == OrderId);
      return PartialView(orderDetails);
}

You need to create new view to show the grid:

@model IEnumerable<OrdersDetail>
@Html.YourHelper.Grid(model).Html() @*or however you build the grid*@

In this case you will not need to fill the grid manually by the new record, the grid will be refreshed automatically.

I hope this helps




回答2:


In your Create Post action method, you need to handle disconnected approach when working with web technologies like MVC, Web API, WCF etc.

Orders should contain list of OrderDetails, when its read in action parameter. Look for if its editing or addition and change Entity state accordingly to Added or Modified.

This usually happens because in web apps EF doesn't deal with entity tracking. Please refer this link EF disconnected apps. Apply the scenario which are similar to your's.



来源:https://stackoverflow.com/questions/33190604/how-to-insert-to-master-detail-tables-in-asp-net-mvc-5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!