如何将没有超时的订购商品发布到控制器

时间:2014-12-29 20:47:52

标签: jquery asp.net-mvc html5 asp.net-mvc-4 asp.net-web-api

HTML5离线ASP.NET MVC4应用程序允许输入订单数量并为客户提交订单。

在浏览器中呈现的产品列表包含约4000种产品。 只订购了少量特定订单的产品。

使用下面的代码请求超时。浏览器发布所有产品。请求花费太多时间,可能由httpruntime ExecutionTimeout

终止

服务器错误日志显示已收到所有发布的数据。 看起来MVC模型绑定器需要太多时间来从发布的数据创建产品列表。

如何解决这个问题?如何仅发布已输入数量的订购商品或其他想法? 如果这是合理的话,我可以切换到ajax,jquery和MVC4 Web API。

控制器:

public class OfflineOrderController : ControllerBase
{

    [HttpGet]
    public ActionResult Order(string customerId)
    {
        return View(new MobileOrderOrderViewModel(customerId));
    }

    [HttpPost]
    public ActionResult Order(string customerId, [Bind(Prefix = "Products")] IEnumerable<OrderedItems> Result)

    {
      ... save order to database
        return new ContentResult() { Content = "Order received" };
    }


    public AppCacheResult Manifest()
    {
        return new AppCacheResult(new[] { 
            Url.Content("~/Image/Icon/favicon")
        });
    }

}

查看:

<!DOCTYPE html>
<html manifest="~/MobileOrder/Manifest">
<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 { type = "number", min = 0 })
                    </td>
                </tr>
            }
    </table>
    <input type="submit" value="Send order">
@Html.HiddenFor(m => Model.CustomerId)
}
</body>
</html>

视图模型:

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
    }

}

型号:

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

UPDATE2

使用Imrans的代码回答我创建了API控制器来接收订购的产品:

    public class OrderController :ApiController
    {

        public HttpResponseMessage Post(string customerid, [FromBody]List<OrderedItems> products) {
  ....
   }
}

调试器显示产品已过帐但产品参数为空列表。 如何将选定的产品列表传递给Web API?

用于发布的代码是:

<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 productIndex = $(element).prevAll()[1];
                var productIdElement = $(element).prevAll()[0];
                elementsToSend.push(productIndex);
                elementsToSend.push(productIdElement);
                elementsToSend.push(element);
            });
            var dataToPost = $(elementsToSend).serializeArray();
            $.post(BASE_URL + "api/Order?" + $.param({
                customerid: $("#CustomerId").val()
            }), dataToPost);
            return false;
        });
    })
</script>

2 个答案:

答案 0 :(得分:1)

好的,我认为您的观点应该是这样的

<!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>
                        <input type="hidden" name="Products.Index" value="@i"/>
                        @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() {
            $("form").submit(function () {
                var elementsToSend = [];
                var quantityElements = $("input.quantity").filter(function(index, element) {
                    if ($(this).val() != 0) { return true; }
                    else{ return false;}
                });
                $.each(quantityElements, function (index, element) {
                    var productIndex = $(element).prevAll()[1];
                    var productIdElement = $(element).prevAll()[0];
                    elementsToSend.push(productIndex);
                    elementsToSend.push(productIdElement);
                    elementsToSend.push(element);
                });
                elementsToSend.push($("#CustomerId")[0]);
                var dataToPost = $(elementsToSend).serializeArray();
                //send elementsToSend via ajax
                $.post("/OfflineOrder/Order", dataToPost);
                return false;
            });
        })
    </script>
</body>
</html>

这是控制器方法:

[HttpPost]
public ActionResult Order(string customerId, List<OrderedItems> products)
{
    .....
}

希望这有帮助。

答案 1 :(得分:0)

您可以尝试使用AJAX来减轻负担:

$('form').submit(function () {
    var data = $(this).serializeArray().filter(function (k, v) {
        // Filter data based on order rule
    });
    // Send AJAX!
    return false;
});

请记住,这只会劫持默认的HTML表单行为。它可以通过关闭JavaScript来取代。

编辑:确保您使用的是Controller / C#命名约定。否则,绑定可能无效。

orderedItems.push({ Id: items[i].Id, Quantity: items[i].Quantity });
var data = JSON.stringify({ customerId: $("customerId").val(), Result: orderedItems });

使用filter进行列表推导有更好的方法,但你对我有意义。

最后,在Order POST操作中,最好返回JsonResult