skip to Main Content

I know this is some pretty old technology, but this issue with Datatables has been bothering me, and I haven’t found a satisfactory answer on SO that deals with this specifically.

In my code, I have the following AJAX call. It serializes my form, posts the data to my .NET MVC controller, and no errors occur.

var url = "/Student/SectionSearch/";
var vm = $('#sectionSearchForm').serializeArray();

$.ajax({
    type: 'POST',
    url: url,
    dataType: 'json',
    data: vm,
    success: function (result) {
        return false;
    },
    error: function (xhr, ajaxOptions, thrownError) {
        alert('Failed to load sections. Please try again.');
    }
});

Here is the heavily stripped-down form.

@model ViewModels.SectionSearchVM

@using (Html.BeginForm("SectionSearch", "Student", FormMethod.Post, new { @id = "sectionSearchForm" }))
{
    <div>
        <div>
            @Html.LabelFor(model => model.CalendarId)
            @Html.DropDownListFor(model => model.CalendarId, Model.Calendars, "")
        </div>

        <div>
            @Html.LabelFor(model => model.StructureId)
            @Html.DropDownListFor(model => model.StructureId, Model.Structures, "")
        </div>

        <div>
            @Html.LabelFor(model => model.PeriodId)
            @Html.DropDownListFor(model => model.PeriodId, Model.Periods, "")
        </div>

        <div>
            @Html.LabelFor(model => model.TermId)
            @Html.DropDownListFor(model => model.TermId, Model.Terms, "")
        </div>

        <div>
            @Html.LabelFor(model => model.SectionId)
            @Html.DropDownListFor(model => model.SectionId, Model.Sections, "")
        </div>
    </div>

    <div>
        <input id="submitSectionSearch" class="btn btn-primary" type="submit" value="Search">
    </div>
}

In my MVC controller, I can see that the object was populated correctly, and a JSON-encoded list of my objects is returned without issues.

public JsonResult SectionSearch(SectionSearchVM vm)
{
    StudentSearchResults results = _userService.GetStudentsBySectionId(vm.SectionId);
    return Json(results, JsonRequestBehavior.AllowGet);
}

Now I’d like to run the exact same AJAX call, but from within the Datatables construct.

$('#resultsDataTable').DataTable({
    info: false,
    bFilter: false,
    bLengthChange: false,
    iDisplayLength: 10,
    dom: 'rtp',
    order: [[1, "asc"]],

    language: {
        emptyTable: "There are no students that meet your search criteria."
    },
    ajax: {
        type: 'POST',
        url: url,
        dataType: 'json',
        data: vm,
        dataSrc: function (result) {
            ... data manipulation ...    
            return result.Results;
        },
    },
    "autoWidth": false,

    "columnDefs": [
        {
            "targets": 0,
            "data": "StudentNumber",
        },
        {
            "targets": 1,
            "data": "FullName",
            "width": "70%"
        }
    ]
});

Inexplicably, this fails on the Controller side. The action is called correctly, but when debugging the code, I can see that my VM object is empty (all properties NULL).

I’ve tried doing some creative things to the datatables data object, including JSON.stringify(), serialize(), data: { "data": vm } but to no avail. I could change the endpoint to just accept a long query string of values, but to me, that defeats the purpose of serialization, and still doesn’t explain why my AJAX call fails under slightly different circumstances.

Am I missing something fundamentally obvious here?

Update:
It turns out there is a huge difference in the payloads that are passed between the standard AJAX call and the datatables version…

Standard:

CalendarId=6019&StructureId=10462&PeriodId=50141&TermId=21203&SectionId=3314793

Datatables:

0%5Bname%5D=CalendarId&0%5Bvalue%5D=6019&1%5Bname%5D=StructureId&1%5Bvalue%5D=10462&2%5Bname%5D=PeriodId&2%5Bvalue%5D=50141&3%5Bname%5D=TermId&3%5Bvalue%5D=21203&4%5Bname%5D=SectionId&4%5Bvalue%5D=3314793

Clearly that is part of my problem, but I still don’t understand the hows or whys of it.

2

Answers


  1. Chosen as BEST ANSWER

    Unfortunately, I wasn't able to find a satisfactory reason for why this occurs with DataTables, so I'm back to using workarounds.

    Here is the setup I went with, in the off-chance this might help someone else.

    var vm = $('#sectionSearchForm').serializeArray();
    var url = "/Student/SectionSearch/" + "?" + vm;
    
    $('#resultsDataTable').DataTable({
        dom: 'rtp',
        order: [[1, "asc"]],
        language: {
            emptyTable: "There are no students that meet your search criteria."
        },
        ajax: {
            type: 'POST',
            url: url,
            dataType: 'json',
            data: null
        },
        "columnDefs": [
            {
                "targets": 0,
                "data": "StudentNumber",
            },
            {
                "targets": 1,
                "data": "FullName",
                "width": "70%"
            }
        ]
    });
    

    Essentially, I nulled out the data parameter, and attached the serialized form as a huge query string on my URL. Not ideal, but it satisfied the DataTables construct.


  2. I think the problem is in the form selector, where data is not serialize

    as you using

    var form = $('#sectionSearchForm');
        var vm = $(form).serializeArray();
    

    try these

    var vm = $("form").serializeArray();
    

    and

    var vm = $("form").serialize();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search