问题
Version 1.10 of jQuery DataTables changes a ton of things from the previous versions of DataTables, including how it handles the Ajax requests and responses.
The developers of the library do not have any experience working with an ASP.NET backend, so although some of the nuances of WebMethods have been brought up to them in the past, they apparently didn't consider them in this version.
For example, the dataSrc
DataTables option should be where we deal with the fact that ASP.NET WebMethods wrap all of their Ajax responses with {d: [response]}
.
Instead, DataTables only looks at the dataSrc
setting to find the data property, not the rest of the required response information (draw
, recordsTotal
, recordsFiltered
, and error
). My memory could be incorrect, but I'm pretty sure the dataSrc
setting used to handle this just fine.
回答1:
To handle JSON response from the server in format {d: { data: [] } }
, you can use DataTables initialization option dataSrc as follows "dataSrc": "d.data"
.
However it only works for client-side processing mode.
Client-side processing mode only
$('#example').dataTable({
"ajax": {
"url": "Default.aspx/GetSearchResults",
"type": "POST",
"contentType": "application/json; charset=utf-8",
"dataType": "json",
"data": function (d) {
return JSON.stringify(d);
},
"dataSrc": "d.data"
}
});
Universal solution
fot client-side and server-side processing modes
In server-side processing mode we need to let DataTables access other variables that the server-side script sends, such as draw
, recordsTotal
, etc. To do so we need to use callback for dataSrc option and copy json.d
properties into json
and get rid of d
property.
$('#example').dataTable({
"ajax": {
"url": "Default.aspx/GetSearchResults",
"type": "POST",
"contentType": "application/json; charset=utf-8",
"dataType": "json",
"data": function (d) {
return JSON.stringify(d);
},
"dataSrc": function(json){
for(key in json.d){ json[key] = json.d[key]; }
delete json['d'];
return json.data;
}
}
});
回答2:
You can use EnablePageMethods on the ScriptManager and call them directly from the PageMethods object which will not have the returned data nested in .d.
回答3:
Below is my solution. There may be an easier way to do this, but the way I setup dataTables below seemed to be most reusable way of sending and receiving JSON to a ASP.NET WebMethod. Please post other ways that have worked for you. Hopefully someone will have a less wonky way of doing the "d" thing.
var $table = $('#TableId');
var url = 'page.aspx/WebMethodName';
var extraData = {
something: 'value1',
somethingElse: 'value2'
};
Event handler handles receiving the data from the server. I move everything from the d property into the root of the object.
$table.on('xhr.dt', function (e, settings, json)
{
/// <summary>
/// Fix for asp.net WebMethod compatibility.
/// If json has a d property, then response came from a WebMethod.
/// DataTables needs the contents of the d property to be in the root.
/// </summary>
/// <param name="e">The jQuery event object.</param>
/// <param name="settings">The jquery.DataTables settings object.</param>
/// <param name="json">The data returned from the server.</param>
if(json.d)
{
var data = json.d;
// Clear out json.d to free up memory
json.d = undefined;
$.extend(json, data);
}
// Note no return - we have to manipulate the data directly in the JSON object.
// WHY, OH WHY, CAN'T WE JUST RETURN?
}
);
DataTable initialization. I serialize the data to send to the server as late as possible to give myself plenty of opportunity to add to the request.
$table.DataTable({
ajax: {
{
url: url,
type: 'POST',
contentType: 'application/json',
processData: false, // important so the raw data makes it to the beforeSend handler
beforeSend:function( jqXHR, settings )
{
/// <summary>
/// Converts to json for transmission and adds any extra data desired.
/// </summary>
/// <param name="jqXHR">The jqXHR object.</param>
/// <param name="settings">The settings object.</param>
/// <param name="data">The data that will be sent to the server.</param>
var data = settings.data;
// I postponed the serialization as long as possible, so this is the
// last chance to attach extra data to send along
data.extraData = extraData;
settings.data = JSON.stringify({ WebMethodParameterName: data });
}
}
}
});
On the server side I've created classes to model the structure that dataTables sends and requires as a response. T is the type for each row of data. The DataTablesResponse has a constructor overload which takes the request.draw value and sticks it in the response so I don't have to remember.
[WebMethod]
public static DataTablesResponse<T> WebMethodName(DataTablesRequest request)
{
var response = new DataTablesResponse<T>(request);
// Do something to get my data
List<T> results = GetMyData();
response.data = results;
return response;
}
As a side note, I attempted to post this to the dataTables.net forums, but I can't get it past draft for some reason... so it will live here instead.
回答4:
You can use dataFilter function in your ajax call to strip the d property. Note if your dataType is json, you need stringify your object back to string as the ajax will parse the returned data to json again.
ajax: {
type: "POST",
contentType: "application/json; charset=utf-8",
url: "...",
dataType: 'json',
dataFilter: function (data) {
//data is raw string, convert to json object first
//must return string if the dataType is set to json and the jQuery ajax will parse the returned data again
var msg = jq.parseJSON(data);
if (msg.hasOwnProperty('d')) {
return JSON.stringify(msg.d);
} else
return data;
}
}
来源:https://stackoverflow.com/questions/27626843/how-do-you-send-and-receive-json-with-jquery-datatables-1-10-to-a-asp-net-webmet