How to pass products and quantities to ASP.NET MVC

2019-09-10 09:58发布

ASP.NET MVC4 applications allows to enter ordered product quantities and passses them to Web API controller.

Controller receives empty product list as product parameter. Debugger shows that data is posted. How to refactor view so that products can passed to Web API ?

View:

@inherits ViewBase<MyApp.MobileOrderOrderViewModel>
<!DOCTYPE html>
<html>
<body>
    @using (Html.BeginForm())
    {
        <table>
            @for (int i = 0; i < Model.Products.Count; i++)
            {
                <tr>
                    <td>@Model.Products[i].Id</td>
                    <td>
                        @Html.HiddenFor(m => Model.Products[i].Id)
                        @Html.TextBoxFor(m => Model.Products[i].Quantity, new { @class="quantity", type = "number", min = 0 })
                    </td>
                </tr>
            }
        </table>
        <input type="submit" value="Send order">
        @Html.HiddenFor(m => Model.CustomerId)
    }


<script>
    $(function () {
        "use strict";
        var BASE_URL = '@Url.Content("~/")';
        $("form").submit(function (ev) {
            var elementsToSend = [];
            ev.preventDefault();
            var quantityElements = $("input.quantity").filter(function (index, element) {
                if ($(this).val() != 0) {
                    return true;
                }
                else {
                    return false;
                }
            });

            $.each(quantityElements, function (index, element) {
                var productIdElement = $(element).prevAll()[0];
                elementsToSend.push(productIdElement);
                elementsToSend.push(element);
            });
            var dataToPost = $(elementsToSend).serializeArray();
            $.post(BASE_URL + "api/Order?" + $.param({
                klient: $("#CustomerId").val()
            }), dataToPost);
        });
    })
</script>

ViewModel:

public class MobileOrderOrderViewModel : ViewModelBase
{
    public string CustomerId { get; set; }

    public List<OrderedItems> Products { get; set; }

 public MobileOrderOrderViewModel( string customer ) {
    CustomerId = customer;
    ... populate Products property from database
    }

}

Model:

    public class OrderedItems
    {
        public string Id;
        public decimal Quantity;
    }

WebAPI Controller:

    public class OrderController :ApiController
    {

        public HttpResponseMessage Post(string customerid, [FromBody]List<OrderedItems> products) {
   // Why  products.Count() is 0 here ?
  ...
   }
}

Update

I changed code according to answer. alert() shows that string is in format described in answer but products parameter is still empty.

chrome shows that request type is

Content-Type:application/x-www-form-urlencoded;

but buffer contains json string. Maybe this confuses Web API. How to fix ?

        $.each(quantityElements, function (index, element) {
            var productIdElement = $(element).prevAll()[0];
            var product = {
                id: $(productIdElement).val(),
                quantity: $(element).val()
            };
            elementsToSend.push(product);
        });

        var dataToPost = JSON.stringify(elementsToSend);
        $.post(BASE_URL + "api/Order?" + $.param({
            customerid: $("#CustomerId").val()
        }), dataToPost);

1条回答
Anthone
2楼-- · 2019-09-10 10:26

The problem is with your data serialization.

In order to be properly binded it has to be in the following format:

"products" : [ 
              {"id":1, "quantity":20},
              {"id":5, "quantity":100},
              ...
             ]

In your case the following code produces a wrong output:

 $.each(quantityElements, function (index, element) {
                var productIdElement = $(element).prevAll()[0];
                elementsToSend.push(productIdElement);
                elementsToSend.push(element);
            });

If I'am not wrong it produces something like:

[ 
   {name:"id[1]", value:1},
   {name:"quantity[1]", value:20}
   {name:"id[2]", value:5},
   {name:"quantity[2]", value:100}
   ...
]

You can fix this by something like:

$.each(quantityElements, function (index, element) {
      var productIdElement = $(element).prevAll()[0];
      var product = {
           id : $(productIdElement).val(),
           quantity : $(element).val()
       };

       products.push(product);
 });

Than instead of serializeArray() use JSON.stringify(products)

UPDATE

Try posting it to the server with:

$.post(BASE_URL + "api/Order?" + $("#CustomerId").val(), products);

P.S in this case you don't have to stringify products object because .$post supports plain objects as well

查看更多
登录 后发表回答