Bado
Bado

Reputation: 81

Post knockout.js viewmodel to .Net Core (2.0) MVC Controller

Overview:

Currently, I try to create an ASP.NET Core MVC website which gets data from the server on page load. After that, the page uses knockout.js to maintain a viewmodel to update the data sent from the server (in the first step). Finally, there is a button which sends the edited data back to the server (through an AJAX request). But the corresponding value in my server method is always empty.

Current Approach:

First, there is my model class.

    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;
        }
    }

In my view I use the model class as a List (List) and load the data like this:

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
        });
    })

The viewModel is defined like this (shortend for readability):

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

Now after someone hits the mentioned update button I call this javascript function:

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');
                }
            });
        }

Here you can see that I use the ko.toJSON method to convert the observableArray to a JSON String and use this string as the data argument for the ajax post.

The ConfirmOrder method in the MVC Controller looks like this currently:

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

There is no logic yet cause the offers list is created (so not null) but the count of list items is always 0.

In a concret example this is the JSON string I receive from the server while load the view:

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

And this is the string i produce with the ajax call:

[{"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}]

What have I tried already:

Is there a master somewhere which can help me with this problem? (If you need some more information please do not hesitate to ask)

Upvotes: 0

Views: 844

Answers (1)

Bado
Bado

Reputation: 81

Thanks to the input of @adiga I have found the solutions for (my) error.

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

This is the working solution. I thought I already have tried it but maybe I have forgoten the content-type for the ajax post.

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');
    }
});

Thanks again for all responses!

Upvotes: 1

Related Questions