简体   繁体   English

MVC 将复杂对象传递给控制器​​以进行保存

[英]MVC Passing a Complex Object to the controller for saving

I am writing a web page with MVC and Entity Framework.我正在用 MVC 和实体框架编写一个网页。 I have an order with line items attached and want to return a complex object to the controller for processing.我有一个附有订单项的订单,想将一个复杂的对象返回给控制器进行处理。

I have now included all the code.我现在已经包含了所有代码。

My view :我的观点

@model BCMManci.ViewModels.OrderCreateGroup

@{
    ViewBag.Title = "Create";
}
<h2>New Order</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <h4>@Html.DisplayFor(model => model.Order.Customer.FullName)</h4>

    <table>
        <tr>
            <td><b>Order Date:</b> @Html.DisplayFor(model => model.Order.OrderDate)</td>
            <td><b>Status:</b> @Html.DisplayFor(model => model.Order.OrderStatus.OrderStatusName)</td>
        </tr>
        <tr>
            <td colspan="2">
                <b>Notes</b>
                @Html.EditorFor(model => model.Order.Notes, new { htmlAttributes = new { @class = "form-control" } })
            </td>
        </tr>
    </table>
        @Html.ValidationMessageFor(model => model.Order.Notes, "", new { @class = "text-danger" })
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })


        <table class="table table-striped table-hover">
            <thead>
                <tr>
                    <td>Name</td>
                    <td>Price</td>
                    <td>Discount</td>
                    <td>Total</td>
                    <td>Quantity</td>
                </tr>
            </thead>
            <tbody>
                @foreach (var product in Model.ProductWithPrices)
                {
                    <tr>
                        <td>
                            @Html.DisplayFor(modelItem => product.ProductName)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => product.SellingPrice)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => product.DiscountPrice)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => product.TotalPrice)
                        </td>
                        <td>
                            @Html.EditorFor(modelItem => product.Quantity, new { htmlAttributes = new { @class = "form-control" } })
                        </td>
                    </tr>
                }
            </tbody>
        </table>

        <input type="submit" value="Create" class="btn btn-default" />
}
<div class="btn btn-danger">
    @Html.ActionLink("Cancel", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")

} }

Controller :控制器

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Order,ProductWithPrices,Order.Note,product.Quantity")] OrderCreateGroup order)
    {
        try
        {
            if (ModelState.IsValid)
            {
                db.Orders.Add(order.Order);

                foreach (var orderItem in order.ProductWithPrices.Select(item => new OrderItem
                {
                    OrderId = order.Order.OrderId,
                    ProductId = item.ProductId,
                    Quantity = item.Quantity,
                    ItemPrice = item.SellingPrice,
                    ItemDiscount = item.DiscountPrice,
                    ItemTotal = item.TotalPrice
                }))
                {
                    db.OrderItems.Add(orderItem);
                }
                db.SaveChanges();
                return RedirectToAction("ConfirmOrder", new {id = order.Order.OrderId});
            }
        }
        catch (DataException /* dex */)
        {
            //TODO: Log the error (uncomment dex variable name and add a line here to write a log.
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
        }
        ViewBag.Products = db.Products.Where(model => model.IsActive == true);

        PopulateDropdownLists();
        return View(order);
    }

Data Source :数据来源

public class OrderCreateGroup
{
    public OrderCreateGroup()
    {
        ProductWithPrices = new List<ProductWithPrice>();
    }

    public Order Order { get; set; }
    public ICollection<ProductWithPrice> ProductWithPrices { get; set; }
}

public class ProductWithPrice : Product
{
    public decimal SellingPrice { get; set; }
    public decimal DiscountPrice { get; set; }

    public int Quantity { get; set; }

    public decimal TotalPrice { get; set; }
}

However, the values that are entered on the form are not being passed, through.但是,在表单上输入的值不会被传递。 So I can't access them in the controller.所以我无法在控制器中访问它们。 The 'productWithPrices' collection is null although there is Data in it on the web page. 'productWithPrices' 集合为空,尽管网页上有数据。

I have tried making it asyc and also tried changing the ActionLink button like below but it didn't get to the controller.我尝试将其设为异步,并尝试更改如下所示的 ActionLink 按钮,但它没有到达控制器。

@Html.ActionLink("Create", "Create", "Orders", new { orderCreateGoup = Model }, null)

This is the controller but it now doesn't make sense as the parameter passed in the datasource for the page.这是控制器,但它现在没有意义,因为在页面的数据源中传递的参数。

public ActionResult Create(OrderCreateGroup orderCreateGoup)

Please, can you give me direction on the best way of doing this?拜托,你能告诉我这样做的最佳方式吗?

In your OrderCreateGroup class initialize the collection to an empty list.在您的OrderCreateGroup类中,将集合初始化为空列表。

public class OrderCreateGroup
{
    public OrderCreateGroup()
    {
       ProductWithPrices = new List<ProductWithPrice>();
    }
    public Order Order { get; set; }
    public ICollection<ProductWithPrice> ProductWithPrices { get; set; }
}

You'll need to add @Html.HiddenFor(m => m.SellingPrice) and similarly for other bound fields that are using DisplayFor if you want to post them back to the controller.您需要添加@Html.HiddenFor(m => m.SellingPrice)以及类似的其他使用 DisplayFor 的绑定字段,如果您想将它们发回控制器。

Note: For your benefit, try to have a look at the generated HTML code when your page is rendered in the browser and see what tags are generated inside the <form> tag with a name attribute.注意:为了您的利益,当您的页面在浏览器中呈现时,请尝试查看生成的 HTML 代码,并查看在带有 name 属性的<form>标记内生成了哪些标记。

make sure you bind the appropriate property from the complex object, like the following:确保从复杂对象绑定适当的属性,如下所示:

@model  BCMManci.ViewModels.OrderCreateGroup

...
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">


        ...
        <div class="form-group">
            @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.OrderCreateGroup.Order.Quantity, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.OrderCreateGroup.Order.Quantity, "", 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>

Note :model.OrderCreateGroup.Order.Quantity would be one the your order's property.注意:model.OrderCreateGroup.Order.Quantity 将是您订单的属性之一。 hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM