Convert pure JS grid to work with MVC controller

3 posts, 0 answers
  1. Shea
    Shea avatar
    58 posts
    Member since:
    Feb 2013

    Posted 15 Oct 2013 Link to this post

    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. Shea
    Shea avatar
    58 posts
    Member since:
    Feb 2013

    Posted 16 Oct 2013 Link to this post

    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....
  3. Petur Subev
    Admin
    Petur Subev avatar
    1882 posts

    Posted 17 Oct 2013 Link to this post

    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!
Back to Top