ASP.NET MVC主从录入表单

20

我正在尝试使用ASP.NET MVC实现订单录入表单,但遇到了很多困难。所有我找到的示例都与查看主细节表单有关,没有关于添加或编辑的。

假设我有两个表:Order和OrderLines,它们之间存在一对多的关系。在主视图中,我有一个“New”按钮,当点击它时,应该显示一个新的订单视图,由订单字段、显示订单行的网格和一个“Save”按钮组成,当用户点击“Save”按钮时,将整个订单连同其行保存到数据库中。该网格应该有三个按钮:“添加行”,“编辑行”,和“删除行”。当点击“添加行”时,应该显示一个新的视图,允许用户将行添加到订单视图网格行中-此时不涉及数据库。当用户点击“编辑行”时,应该显示一个视图,允许用户编辑所选行并在完成后更新订单网格行。

最困难的问题是:

如何在订单视图和订单行视图之间传递订单及其行集合?

如何根据订单行视图中的更改更新订单视图?

如何在视图之间持久化更改而不涉及数据库?

是否有一个具体的示例展示如何使用MVC实现这个功能?

Views

感谢您的帮助和反馈。

6个回答

3
请查看我的博客文章,其中介绍了如何在asp.net mvc中创建主从表单,并提供了可下载的演示项目:blog post

2
与WebForms不同,ASP.NET MVC不会试图隐藏HTTP的无状态特性。要在多个表单中使用复杂对象,您有几个选项:
  • 每次更改时将对象保存在服务器上,以便只使用ID即可获取更新后的对象
  • 使用jquery填充订单行表单并将详细信息保存到主表单中
我通常自己选择客户端选项,主表单具有用于在子表单中编辑的数据的隐藏字段。如果您真的不想涉及数据库,则可能会发现服务器端选项更容易,您可以在会话中保留部分更新的对象。

1
谢谢。您可以提供一个使用JQuery方法的简短示例吗? - Emad

2
步骤1:创建视图模型
public class OrderVM
{
    public string OrderNo { get; set; }
    public DateTime OrderDate { get; set; }
    public string Description { get; set; }
    public List<OrderDetail> OrderDetails {get;set;}
}

步骤二:添加JavaScript以添加订单行。
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

    $(function () {
        $('#orderDate').datepicker({
            dateFormat : 'mm-dd-yy'
        });
    });

    $(document).ready(function () {
        var orderItems = [];
        //Add button click function
        $('#add').click(function () {
            //Check validation of order item
            var isValidItem = true;
            if ($('#itemName').val().trim() == '') {
                isValidItem = false;
                $('#itemName').siblings('span.error').css('visibility', 'visible');
            }
            else {
                $('#itemName').siblings('span.error').css('visibility', 'hidden');
            }

            if (!($('#quantity').val().trim() != '' &amp;&amp; !isNaN($('#quantity').val().trim()))) {
                isValidItem = false;
                $('#quantity').siblings('span.error').css('visibility', 'visible');
            }
            else {
                $('#quantity').siblings('span.error').css('visibility', 'hidden');
            }

            if (!($('#rate').val().trim() != '' &amp;&amp; !isNaN($('#rate').val().trim()))) {
                isValidItem = false;
                $('#rate').siblings('span.error').css('visibility', 'visible');
            }
            else {
                $('#rate').siblings('span.error').css('visibility', 'hidden');
            }

            //Add item to list if valid
            if (isValidItem) {
                orderItems.push({
                    ItemName: $('#itemName').val().trim(),
                    Quantity: parseInt($('#quantity').val().trim()),
                    Rate: parseFloat($('#rate').val().trim()),
                    TotalAmount: parseInt($('#quantity').val().trim()) * parseFloat($('#rate').val().trim())
                });

                //Clear fields
                $('#itemName').val('').focus();
                $('#quantity,#rate').val('');

            }
            //populate order items
            GeneratedItemsTable();

        });
        //Save button click function
        $('#submit').click(function () {
            //validation of order
            var isAllValid = true;
            if (orderItems.length == 0) {
                $('#orderItems').html('&lt;span style="color:red;"&gt;Please add order items&lt;/span&gt;');
                isAllValid = false;
            }

            if ($('#orderNo').val().trim() == '') {
                $('#orderNo').siblings('span.error').css('visibility', 'visible');
                isAllValid = false;
            }
            else {
                $('#orderNo').siblings('span.error').css('visibility', 'hidden');
            }

            if ($('#orderDate').val().trim() == '') {
                $('#orderDate').siblings('span.error').css('visibility', 'visible');
                isAllValid = false;
            }
            else {
                $('#orderDate').siblings('span.error').css('visibility', 'hidden');
            }

            //Save if valid
            if (isAllValid) {
                var data = {
                    OrderNo: $('#orderNo').val().trim(),
                    OrderDate: $('#orderDate').val().trim(),
                    //Sorry forgot to add Description Field
                    Description : $('#description').val().trim(),
                    OrderDetails : orderItems
                }

                $(this).val('Please wait...');

                $.ajax({
                    url: '/Home/SaveOrder',
                    type: "POST",
                    data: JSON.stringify(data),
                    dataType: "JSON",
                    contentType: "application/json",
                    success: function (d) {
                        //check is successfully save to database 
                        if (d.status == true) {
                            //will send status from server side
                            alert('Successfully done.');
                            //clear form
                            orderItems = [];
                            $('#orderNo').val('');
                            $('#orderDate').val('');
                            $('#orderItems').empty();
                        }
                        else {
                            alert('Failed');
                        }
                        $('#submit').val('Save');
                    },
                    error: function () {
                        alert('Error. Please try again.');
                        $('#submit').val('Save');
                    }
                });
            }

        });
        //function for show added items in table
        function GeneratedItemsTable() {
            if (orderItems.length &gt; 0) {
                var $table = $('&lt;table/&gt;');
                $table.append('&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Item&lt;/th&gt;&lt;th&gt;Quantity&lt;/th&gt;&lt;th&gt;Rate&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;');
                var $tbody = $('&lt;tbody/&gt;');
                $.each(orderItems, function (i, val) {
                    var $row = $('&lt;tr/&gt;');
                    $row.append($('&lt;td/&gt;').html(val.ItemName));
                    $row.append($('&lt;td/&gt;').html(val.Quantity));
                    $row.append($('&lt;td/&gt;').html(val.Rate));
                    $row.append($('&lt;td/&gt;').html(val.TotalAmount));
                    $tbody.append($row);
                });
                $table.append($tbody);
                $('#orderItems').html($table);
            }
        }
    });

</script>

步骤三:创建保存数据的操作
[HttpPost]
    public JsonResult SaveOrder(OrderVM O)
    {
        bool status = false;
        if (ModelState.IsValid)
        {
            using (MyDatabaseEntities dc = new MyDatabaseEntities())
            {
                Order order = new Order { OrderNo = O.OrderNo, OrderDate = O.OrderDate, Description = O.Description };
                foreach (var i in O.OrderDetails)
                {
                    //
                   // i.TotalAmount = 
                    order.OrderDetails.Add(i);
                }
                dc.Orders.Add(order);
                dc.SaveChanges();
                status = true;
            }
        }
        else
        {
            status = false;
        }
        return new JsonResult { Data = new { status = status} };
    }

您可以下载源代码视频教程


1

谢谢。我觉得我没有表达清楚我的问题!我不是在寻找一个控件。我需要知道当我在ASP.NET MVC中有一个主细节录入表单时,不同视图如何交互。 - Emad
很好,我想提供一个解决方案......该控件可以处理你所描述的许多问题。 - ozz
2
我猜Emad想要完全控制代码,我正在寻找相同的答案,我不想使用Telerik,对于MVC,我不希望最终被绑定到控件,并再次被强制按照控件所需的方式进行编程,这一次我想保持“自由”。 - Nestor
此外,Devexpress还有一个带有主/从能力的网格控件http://mvc.devexpress.com/GridView/MasterDetailcontrol。但是Telerik和DevEx网格控件的主/从示例仅用于查看而不是添加或编辑。 - AlejandroR

1

就我个人而言(一种大脑倾泻)...

  • 你可以在表单中有一个主网格部分。这将是从操作加载的完整视图(取决于是否加载现有视图及其订单号)。

  • 当点击事件(新建或编辑)时,它会以“灯箱”样式打开一个局部视图。然后将返回一个Json对象回到主表单。

  • 传递的Json对象将使用模板呈现到表格底部(为新记录)或更新现有记录。这也可以在同一个Ajax调用中保存回服务器。或者只是更新客户端并需要用户单击保存按钮。

  • 需要一个isDirty标志,因此任何更改都将将其设置为true,并且当浏览器尝试离开或关闭等时,您可以提示用户保存或不保存。

希望能对您有所帮助。

编辑

尚未尝试过此方法,但与问题的非数据库方面可能会产生有趣的结果 click


0

步骤三:创建保存数据的操作。 [HttpPost]

    public JsonResult SaveOrder(OrderVM O)

    {

        bool status = false;

        if (ModelState.IsValid)

        {

            using (ManageMobileStoreWebContext dc = new ManageMobileStoreWebContext())

            {

                //Random rnd = new Random();

                //OrderID = rnd.Next(),

                Order order = new Order { OrderNo = O.OrderNo, OrderDate = O.OrderDate, Description = O.Description };

                foreach (var i in O.OrderDetails)

                {

                    if(order.OrderDetails == null)

                    {

                        order.OrderDetails = new List<OrderDetail>();

                    }

                    // i.TotalAmount = 

                    order.OrderDetails.Add(i);

                   //dc.OrderDetails.Add(i);

                }

                dc.Orders.Add(order);

                dc.SaveChanges();

                status = true;

            }

        }

        else

        {

            status = false;

        }

        return new JsonResult { Data = new { status = status } };

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接