0
votes

I have a multiselect kendo ui in kendo ui grid. It works perfectly when reading values from remote datasource but when it gives error when updating because it is posting multiselect values array in an unexpected way.

js code is below. GetEmployeeTitles method returns a list of string.

    var sharedTitleDataSource = new kendo.data.DataSource({
        transport: {
            read: "./GetEmployeeTitles"
        }
    });

    $("#grid").kendoGrid({
        dataSource: {
            transport: {

                read: {
                    url: "./GetLaborCodes",

                },
                update:
                {
                    url: "./UpdateLaborCode",
                    type: "POST",
                },
                create:
                {
                    url: "./UpdateLaborCode",
                    type: "POST",
                },
                parameterMap: function (data, type) {
                    console.log(data);
                    console.log(type);
                    if (type != "read") {
                        return data;
                    }
                }
            },
            schema: {
                model: {
                    id: "LaborCode_ID",
                    fields: {
                        LaborCode_Name: { type: "string" },
                        LaborCode_Titles: {}
                    }
                }
            },
        },
        editable: true,
        filterable: true,
        sortable: true,
        batch: true,
        resizable: true,
        reorderable: true,
        columns: [{
                field: "LaborCode_Titles",
                template: function (dataItem) {
                    return dataItem.LaborCode_Titles.join(', ');
                },
                title: "Titles",
                editor: function (container, options) {
                    $('<select multiple="multiple" name="' + options.field+'"/>')
                        .appendTo(container)
                        .kendoMultiSelect({
                            suggest: true,
                            dataSource: sharedTitleDataSource,
                            valuePrimitive: true,
                            autoWidth: true
                        });
                }
            },
        {
            field: "LaborCode_Name",
            title: "Name",
            editor: function (container, options) {
                var input = $('<textarea maxlength="450" name="' + options.field + '"></textarea>');
                input.appendTo(container);
            },
            template: function (dataItem) {
                if (dataItem.LaborCode_Name != null) {
                    return '<span title="' + dataItem.LaborCode_Name + '">' + dataItem.LaborCode_Name.substring(0, 30) + '...' + '</span>';
                }
                return '';
            }
        }
        ]
    });

And here is my viewmodel class:

public class LaborCodeViewModel
{
    public string LaborCode_Name { get; set; }
    public long LaborCode_ID { get; set; }
    public string[] LaborCode_Titles { get; set; }
}

And my update method in backend, nothing special, it just updates the database:

    [HttpPost, ValidateInput(false)]
    public JsonResult UpdateLaborCode(LaborCodeViewModel UpdatedM)
    {
        UpdatedM.LaborCode_ID = RateSheetAppFactory.UpdateInsertNewLaborCode(UpdatedM);
        return Json(UpdatedM, JsonRequestBehavior.AllowGet);
    }

The problem is LaborCode_Titles propery of LaborCodeViewModel is null. When i check the request from the developer tools, the Form Data is like this:

LaborCode_Name: Project Executive
LaborCode_Titles[]: Sr. Project Manager
LaborCode_Titles[]: Lead Designer

But it has to be like this:

LaborCode_Name: Project Executive
LaborCode_Titles: [Sr. Project Manager,Lead Designer]

When i write the data in parameterMap function to console, nothing is wrong:

LaborCode_ID: 5
LaborCode_Name: "Project Executive"
LaborCode_Titles: (2) ["Sr. Project Manager", "Lead Designer"]

How can i post LaborCode_Titles in request as an array? Insead of

LaborCode_Titles[]: Sr. Project Manager

i want to send it like this

LaborCode_Titles: [Sr. Project Manager]

1
I think your problem stems from the fact that you've not specified a contentType for your transport operations, most importantly the update operation. In this case, it will default to using application/x-www-form-urlencoded which unfortunately doesn't handle arrays very well. If your service endpoint can handle JSON data, you should probably send it in that form instead (where the arrays will be serialized in a more sensible way).Joe Glover

1 Answers

0
votes

I'm assuming your service can cope with JSON data, in which case your simplest solution is to post your data in that format. I've modified your datasource to demonstrate what's needed:

  1. alter the content-type HTTP header sent to the server, to indicate that the payload is JSON
  2. serialize the data into JSON as part of the parameterMap function

According to the kendo documentation this is a primary reason to use the parameterMap function:

The function which converts the request parameters to a format suitable for the remote service. By default, the data source sends the parameters using jQuery conventions. The parameterMap method is often used to encode the parameters in JSON format.

$("#grid").kendoGrid({
    dataSource: {
        transport: {
            read: {
                url: "./GetLaborCodes",
            },
            update:
            {
                url: "./UpdateLaborCode",
                contentType: "application/json",
                type: "POST",
            },
            create:
            {
                url: "./UpdateLaborCode",
                contentType: "application/json",
                type: "POST",
            },
            parameterMap: function (data, type) {
                console.log(data);
                console.log(type);
                if (type != "read") {
                    return JSON.stringify(data);
                }
            }
        },
        schema: {
            model: {
                id: "LaborCode_ID",
                fields: {
                    LaborCode_Name: { type: "string" },
                    LaborCode_Titles: {}
                }
            }
        },
    }
});