Home > database >  AJAX Post no longer works when using DataTables
AJAX Post no longer works when using DataTables

Time:06-07

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"  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[name]=CalendarId&0[value]=6019&1[name]=StructureId&1[value]=10462&2[name]=PeriodId&2[value]=50141&3[name]=TermId&3[value]=21203&4[name]=SectionId&4[value]=3314793

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

CodePudding user response:

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

CodePudding user response:

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.

  • Related