【问题标题】:Post knockout.js viewmodel to .Net Core (2.0) MVC Controller将 knockout.js 视图模型发布到 .Net Core (2.0) MVC 控制器
【发布时间】:2018-04-22 04:43:03
【问题描述】:

概述

目前,我尝试创建一个 ASP.NET Core MVC 网站,该网站在页面加载时从服务器获取数据。之后,页面使用 knockout.js 维护一个视图模型来更新从服务器发送的数据(在第一步中)。最后,有一个按钮将编辑后的数据发送回服务器(通过 AJAX 请求)。但是我的服务器方法中对应的值总是空的。

当前方法

首先是我的模型类。

    public class Order
    {
        public string Name { get; set; }
        public int TemplateId { get; set; }
        public decimal Price { get; set; }

        public int Contingent { get; set; }
        public int MaximumOrder { get; set; }
        public int UserOrderCount { get; set; }

        public Order() { }
        public Order(SnackOffer offer)
        {
            Name = offer.Template.Name;
            TemplateId = offer.Template.SnackTemplateId;
            Price = offer.Price;
        }
    }

在我看来,我将模型类用作列表(List)并像这样加载数据:

var model = new viewModel();
    @(Json.Serialize(Model.Offers)).forEach(function (item, index) {
        model.offers.push({
            name: item.name,
            templateId: item.templateId,
            contingent: ko.observable(item.contingent),
            userOrderCount: ko.observable(item.userOrderCount),
            price: item.price,
            maximumOrder: item.maximumOrder
        });
    })

viewModel 是这样定义的(为了可读性而缩写):

function viewModel() {
        var self = this;
        self.offers = ko.observableArray();
}

现在,当有人点击提到的更新按钮后,我称之为 javascript 函数:

self.ConfirmOrder = function () {
            var data = ko.toJSON(self.offers);

            $('#overlay').css('display', 'block');
            $.ajax({
                type: 'post',
                url: '/Snack/ConfirmOrder',
                data: data,
                contentType: 'application/json; charset=utf-8',
                success: function (result) {
                    $('#overlay').css('display', 'none');
                },
                error: function (result) {
                    console.log(result);
                    $('#overlay').css('display', 'none');
                }
            });
        }

在这里你可以看到我使用 ko.toJSON 方法将 observableArray 转换为 JSON 字符串,并将此字符串用作 ajax 帖子的数据参数。

MVC Controller 中的 ConfirmOrder 方法目前如下所示:

    [HttpPost]
    public void ConfirmOrder(List<OrderSnackViewModel.Order> offers)
    {
        foreach (var item in offers)
        {
            _logger.LogInformation(item.Name);
        }            
    }

目前还没有逻辑导致报价列表被创建(所以不为空),但列表项的计数始终为 0。

在一个具体的例子中,这是我在加载视图时从服务器收到的 JSON 字符串:

[{"name":"Test","templateId":1,"price":1.94,"contingent":4,"maximumOrder":7,"userOrderCount":0},{"name":"测试 1","templateId":2,"price":1.50,"contingent":30,"maximumOrder":7,"userOrderCount":0}]

这是我通过 ajax 调用生成的字符串:

[{"name":"Test","templateId":1,"contingent":4,"userOrderCount":0,"price":1.94,"maximumOrder":7},{"name":"测试 1","templateId":2,"contingent":30,"userOrderCount":0,"price":1.5,"maximumOrder":7}]

我已经尝试了什么:

  • 我尝试在我的 MVC 控制器中使用 FromBody
  • 我尝试在 JSON 输出前加上名称 offer,以便我的控制器方法可以将 JSON 字符串项映射到对象。 (例如 data = '{ "offers":' + data + '}'; )
  • 我尝试重命名模型的属性以完全匹配 JSON 名称。因此,我将 Name 重命名为 name,将 Contingent 重命名为 contingent,依此类推。
  • 我尝试在 MVC 控制器操作中使用数组而不是列表

有没有高手可以帮我解决这个问题? (如果您需要更多信息,请随时询问)

【问题讨论】:

  • 试试var data = JSON.stringify({ offers: ko.toJS(self.offers)})
  • 您好,感谢您的快速响应。我已经按照您的建议进行了尝试,但行为没有改变。这是生成的 JSON: {"offers":[{"name":"Test","templateId":1,"contingent":4,"userOrderCount":0,"price":1.94,"maximumOrder":7 },{"name":"Test 1","templateId":2,"contingent":30,"userOrderCount":0,"price":1.5,"maximumOrder":7}]} 所以你认为我的问题是缺少对我的参数的报价名称的引用正确吗?
  • 我不确定。我刚刚看到您已经尝试过FromBody,它应该可以与您的代码一起使用。
  • 确定我现在都试过了。我添加了您的代码行 AND 使用 [FromBody] 属性。如果我这样做,错误至少是别的。现在的错误是,通过这两种更改,offers 参数不是空列表(计数为 0)而是 NULL,所以我的 foreach 通过异常。
  • 它是否符合我的建议?如果是,我会发布一个答案。否则,您可以发布自己的答案并接受它:)

标签: javascript asp.net-mvc knockout.js asp.net-core asp.net-core-mvc


【解决方案1】:

感谢@adiga 的输入,我找到了(我的)错误的解决方案。

[HttpPost]
public JsonResult ConfirmOrder([FromBody]List<Order> offers)
{        
    _logger.LogInformation("COUNT -> " + offers.Count());
    foreach (var item in offers)
    {
        _logger.LogInformation(item.Name);
    }            
}

这是有效的解决方案。我以为我已经尝试过了,但也许我忘记了 ajax 帖子的内容类型。

var data = ko.toJSON(self.offers);

$('#overlay').css('display', 'block');

$.ajax({
    type: 'post',
    url: '/Snack/ConfirmOrder',
    data: data,
    contentType: 'application/json; charset=utf-8',
    success: function (result) {
        //location.reload(); 
        $('#overlay').css('display', 'none');
    },
    error: function (result) {
        console.log(result);
        $('#overlay').css('display', 'none');
    }
});

再次感谢所有回复!

【讨论】:

    猜你喜欢
    • 2016-03-14
    • 1970-01-01
    • 2017-08-20
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多