TJP
TJP

Reputation: 85

Serialize form object and collections with ASP.NET MVC Jquery Ajax

I'm learning ASP.NET MVC 4 using VS 2010 and Jquery 1.7.1. I'm having trouble serializing my collection back to controller. I'm using this Plugin to serialize my model to JSON object.

Here is my Controller:

 public class CustomerController : Controller
{

    public ActionResult Index()
    {
        CustomerViewModel model = new CustomerViewModel();
        model.Orders = GetOrders().ToList();
        return View(model);
    }


    [HttpPost]
    public ActionResult Save(CustomerViewModel model)
    {

        if (ModelState.IsValid)
        {


        }

        return View(model);
    }

    private IEnumerable<Order> GetOrders()
    {
        List<Order> orders = new List<Order>();
        orders.Add(new Order() { OrderID = 1, CustomerID = 1, TotalAmount = 100.99M, OrderName = "Order1", Discount = 5.00M, TotalItems = 5, OrderDate = DateTime.Now });
        orders.Add(new Order() { OrderID = 2, CustomerID = 1, TotalAmount = 101.99M, OrderName = "Order2", Discount = 6.00M, TotalItems = 6, OrderDate = DateTime.Now });
        orders.Add(new Order() { OrderID = 3, CustomerID = 1, TotalAmount = 102.99M, OrderName = "Order3", Discount = 6.00M, TotalItems = 7, OrderDate = DateTime.Now });
        orders.Add(new Order() { OrderID = 4, CustomerID = 1, TotalAmount = 103.99M, OrderName = "Order4", Discount = 7.00M, TotalItems = 8, OrderDate = DateTime.Now });
        orders.Add(new Order() { OrderID = 5, CustomerID = 1, TotalAmount = 104.99M, OrderName = "Order5", Discount = 8.00M, TotalItems = 9, OrderDate = DateTime.Now });
        orders.Add(new Order() { OrderID = 6, CustomerID = 1, TotalAmount = 105.99M, OrderName = "Order6", Discount = 9.00M, TotalItems = 10, OrderDate = DateTime.Now });
        return orders;

    }

}

View:

 <div>
<% using (Html.BeginForm())
   {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
    <legend>Customer Details</legend>
    <table>
        <tr>
            <td>
                <%: Html.LabelFor(m=>m.Customer.FirstName) %>
            </td>
            <td>
                <%: Html.TextBoxFor(m=>m.Customer.FirstName) %>
            </td>
        </tr>
        <tr>
            <td>
                <%: Html.LabelFor(m=>m.Customer.LastName) %>
            </td>
            <td>
                <%: Html.TextBoxFor(m=>m.Customer.LastName) %>
            </td>
        </tr>
        <tr>
            <td>
                <%: Html.LabelFor(m=>m.Customer.EmailAddress) %>
            </td>
            <td>
                <%: Html.TextBoxFor(m => m.Customer.EmailAddress)%>
            </td>
        </tr>
        <tr>
            <td>
                <%: Html.LabelFor(m=>m.Customer.PhoneNumber) %>
            </td>
            <td>
                <%: Html.TextBoxFor(m => m.Customer.PhoneNumber)%>
            </td>
        </tr>
    </table>
    <table id="tblOrdersGrid">
        <tr>
            <th>
                OrderID
            </th>
            <th>
                Order Name
            </th>
            <th>
                Total Amount
            </th>
            <th>
                Total Items
            </th>
        </tr>
        <% foreach (DemoHtmlHelpers.Models.Order order in Model.Orders)
           {%>
        <tr>
            <td id="tdOrderID">
                <%: order.OrderID%>
            </td>
            <td id="tdOrderName">
                <%: order.OrderName%>
            </td>
            <td id="tdTotalAmount">
                <%: order.TotalAmount%>
            </td>
            <td id="tdTotalItems">
                <%: order.TotalItems%>
            </td>
        </tr>
        <%} %>
    </table>
    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
<% } %>
</div>

<script type="text/javascript">

    $(function () {

        $('form').submit(function (e) {

            var customerViewModel = $(this).serializeObject();
            var allOrders = new Array();
            var order = null;
            var orderRows = $('#tblOrdersGrid').find('tr').not(':first');

            $.each(orderRows, function (i, orderItem) {

                order = new Object();
                order.OrderID = $(orderItem).find('#tdOrderID').text();
                order.OrderName = $(orderItem).find('#tdOrderName').text();
                order.TotalAmount = $(orderItem).find('#tdTotalAmount').text();
                order.TotalItems = $(orderItem).find('#tdTotalItems').text();

                allOrders.push(order);
            });

            customerViewModel.Orders = allOrders;
            //customerViewModel['Orders'] = allOrders;

            $.post('<%= Url.Action("Save", "Customer") %>', customerViewModel, function (data) {

                alert('Successfully saved.');
            });
            return false;
        });
    });
</script>

Model Classes:

[Serializable]
public class Customer
{
    public Customer()
    {
        this.CreatedDate = DateTime.Now;
    }

    public int CustomerID { set; get; }

    [Required(AllowEmptyStrings = false)]
    public string FirstName { set; get; }

    [Required(AllowEmptyStrings = false)]
    public string LastName { set; get; }

    [Required(AllowEmptyStrings = false)]
    public string PhoneNumber { set; get; }

    [Required(AllowEmptyStrings = false)]
    public string EmailAddress { set; get; }

    [DataType(DataType.Date)]
    public DateTime CreatedDate { set; get; }

}

[Serializable]
public class Order
{
    public Order()
    {
        this.OrderDate = DateTime.Now;
    }

    public int OrderID { set; get; }

    public int CustomerID { set; get; }

    [Required(AllowEmptyStrings = false)]
    public string OrderName { set; get; }

    [Required()]
    public decimal TotalAmount { set; get; }

    [DataType(DataType.Date)]
    public DateTime OrderDate { set; get; }

    public decimal Discount { set; get; }

    public decimal TotalItems { set; get; }

}

[Serializable]
public class CustomerViewModel
{
    public CustomerViewModel()
    {
        this.Customer = new Customer();
        this.Orders = new List<Order>();
    }

    public Customer Customer { get; set; }
    public List<Order> Orders { get; set; }

}

I can get the customer object back to controller but somehow my order collection is not binding back. Please refer to the screen shots below:

Bind the customer object

Does not bind the orders list

Any clue will be appreciated.

Update 1:

Request in google chrome

Upvotes: 2

Views: 6288

Answers (1)

Erik Philips
Erik Philips

Reputation: 54618

Check out Convert form data to JS object with jQuery. Once you have a nice JS Object, you can add whatever you want. Once you are ready you simply Post the Json to Asp.Net mvc.

var customerViewModel = $(this).ToJson();  // or whatever you call this function
customViewModel.Orders = [];

var orderRows = $('#tblOrdersGrid').find('tr').not(':first');

$.each(orderRows, function (i, orderItem) {
  order = {};
  order.OrderID = $(orderItem).find('#tdOrderID').text();
  order.OrderName = $(orderItem).find('#tdOrderName').text();
  order.TotalAmount = $(orderItem).find('#tdTotalAmount').text();
  order.TotalItems = $(orderItem).find('#tdTotalItems').text();
  customViewModel.Orders.push(order);
});

Then...

$.post('<%= Url.Action("Save", "Customer") %>', 
  JSON.stringify(customerViewModel), 
  function (data) {
    alert('Successfully saved.');
});

Upvotes: 1

Related Questions