This is a migrated thread and some comments may be shown as answers.

Convert pure JS grid to work with MVC controller

2 Answers 294 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Shea
Top achievements
Rank 1
Shea asked on 16 Oct 2013, 12:32 AM
I have a pure JS grid I was using with an asp.net forms backend (.ashx). It has been working fine for six months. I am trying to convert it to an MVC controller for the backend now, but having no luck:

function MaterialsGrid(ticket_ID, grid_id, is_editable, default_billable) {
    var self = this;
    self.ticket_ID = ticket_ID;
    self.GRID_ID = '#' + grid_id;
    self.HANDLER_URL = "/MaterialEntry";
    self.IS_EDITABLE = is_editable;
    self.DEFAULT_BILLABLE = default_billable;
 
    self.material_source = new kendo.data.DataSource({
        batch: true,
        schema: {
            model: {
                id: "MaterialEntryID",
                fields: {
                    MaterialEntryID: { type: "string" },
                    TicketID: { type: "string" },
 
                    ItemID: { type: "number", defaultValue: 0 },
                    ItemName: { type: "string", defaultValue: GridCommon.emptyText },
 
                    Description: { type: "string" },
 
                    Quantity: { type: "number", defaultValue: 0, validation: { required: true, min: 0 } },
 
                    Rate: { type: "number", defaultValue: 0 },
                    Total: { type: "number", defaultValue: 0 },
                     
                    Billable: { type: "boolean", defaultValue: self.DEFAULT_BILLABLE },
                },
            }
        },
 
        transport: {
            read: {
                url: self.HANDLER_URL + "/Read",
                dataType: "json",
                type: "GET",
                cache: false,
            },
            update: {
                url: self.HANDLER_URL + "/Update",
                dataType: "json",
                type: "PUT",
            },
            destroy: {
                url: self.HANDLER_URL + "/Destroy",
                dataType: "json",
                type: "POST",
            },
            create: {
                url: self.HANDLER_URL + "/Create",
                dataType: "json",
                type: "POST",
            },
 
            parameterMap: function (options, operation) {
                if (operation === "read") {
                    return { ticketID: self.ticket_ID };
                }
 
                if (operation === "read") {
                    return { ticketID: self.ticket_ID };
                } else if (options.models) {
                    return { materials: kendo.stringify(options.models), ticketID: self.ticket_ID };
                }
            }
        },
 
        error: GridCommon.showCallBackError
    });
 
    self.items_src = new kendo.data.DataSource({
        transport: {
            read: {
                url: self.HANDLER_URL + "/GetItems",
                dataType: "json",
                type: "GET"
            }
        },
        error: GridCommon.showCallBackError
    });
 
    self.itemDropDownEditor = function (container, options) {
 
        $('<input required data-text-field="ExtendedItemName" data-value-field="ItemName" data-bind="value:' + options.field + '"/>')
            .appendTo(container)
            .kendoDropDownList({
                autoBind: false,
                optionLabel: { ExtendedItemName: GridCommon.emptyText, ItemID: 0 },
                dataSource: self.items_src,
                change: function (e) {
                    options.model.set('ItemID', e.sender.dataItem().ItemID);
                }
            });
    }
 
    self.updateTotal = function (e) {
        var r = e.values.Rate ? e.values.Rate : e.model.Rate;
        var q = e.values.Quantity ? e.values.Quantity : e.model.Quantity;
        e.model.set('Total', q * r);
    }
 
    self.init = function () {
 
        var tools = null;
        var row_commands = null;
        if (self.IS_EDITABLE) {
            tools = [
                { name: "save", text: "Save" },
                { name: "cancel", text: "Cancel" },
                { name: "create", text: "Add" },
                { template: GridCommon.toggleBillableTemplate(self.GRID_ID) }
            ];
            row_commands = [{
                name: "destroy",
                template: '<a href="##" class="k-grid-delete"><img img src="/Content/images/icons/delete.png" /></a>'
            }]
        } else {
            $(self.GRID_ID).addClass('readonly');
        }
        $(self.GRID_ID).kendoGrid({
            toolbar: tools,
 
            save: self.updateTotal,
 
            columns: [
                { field: "ItemName", title: "Item Type", editor: self.itemDropDownEditor },
                { field: "Description" },
                { field: "Quantity", title: "QTY", width: 65, editor: GridCommon.numberEditor },
                { field: "Rate", title: "Price", format: "{0:c}", width: 90, editor: GridCommon.numberEditor },
                { field: "Total", editor: GridCommon.notEditable, format: "{0:c}", width: 95 },
                { field: "Billable", template: '#= GridCommon.getBillableText(Billable) #', width: 100},
                { command: row_commands, width: 40 }
            ],
 
            pageable: false,
            scrollable: true,
            editable: self.IS_EDITABLE,
            navigatable: true,
            sortable: true,
            batch: true,
 
            dataSource: self.material_source,
            saveChanges: GridCommon.saveAll
        });
    }
}

@model Guid
 
<div class="grid-wrapper">
    <div id="materials-data" class="grid-global-save">
        <!-- grid will appear here -->
    </div>
</div>
<script type="text/javascript">
    var mat_grid = new MaterialsGrid('@Model', 'materials-data', true, true);
    $(document).ready(mat_grid.init);
</script>
My material entry controller for the Create function looks like this:
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Create([DataSourceRequest] DataSourceRequest request, IEnumerable<TempVM> materials, string ticketId)
{
    ModelState.Remove("MaterialEntryId");
    ModelState.Remove("Id");
 
    return Json("");
}
public class TempVM
{
    public string MaterialEntryID { get; set; }
    public string TicketID { get; set; }
    public int ItemID { get; set; }
    public string Description { get; set; }
 
}

I know the logic inside create isn't right. But the problem is that the 'materials' parameter is empty when the Create method is called. You can see that the form data seems to be being sent correctly in chrome's Netowork tab, by looking at the attached file.

Any ideas what I am doing wrong?

2 Answers, 1 is accepted

Sort by
0
Shea
Top achievements
Rank 1
answered on 16 Oct 2013, 02:21 PM
Interestingly, I have determined that if I make the 'materials' parameter a string, I do get the correct JSON string, which I can then manually deserialize. So something is causing the the auto-deserialization to work....
0
Petur Subev
Telerik team
answered on 17 Oct 2013, 04:02 PM
Hello Shea,

How to send collection of objects to the server is covered in this blog post:

It requires some special formatting - you cannot just pass it as a single parameter which is stringified.

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx


Kind Regards,
Petur Subev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Tags
Grid
Asked by
Shea
Top achievements
Rank 1
Answers by
Shea
Top achievements
Rank 1
Petur Subev
Telerik team
Share this question
or