Просто быстрое повторное посещение этого старого вопроса ...
Я делаю это так:
var header = datatable.Columns.Cast<DataColumn>().Select(r => new KeyValuePair<string, object>(r.ColumnName, r.DataType.Name));
var data = datatable.Select().AsEnumerable()
.Select(r => r.Table.Columns.Cast<DataColumn>()
.Select(c => new KeyValuePair<string, object>(c.ColumnName, r[c.Ordinal] is DBNull ? null : r[c.Ordinal] )
).ToDictionary(z=>z.Key,z=>z.Value)
);
return new DatatableRequestResponse
{
data = data,
header = header
};