asp.net - net - DataTable a Json utilizando jquery
jquery datatable vb net (9)
Json.NET tiene la capacidad de escribir DataSets / DataTables en JSON.
http://james.newtonking.com/archive/2008/09/06/dataset-datatable-serialization-with-json-net.aspx
Estoy intentando ejecutar un servicio web que devuelve una DataTable con el siguiente fragmento de código:
$.ajax({
type: "POST",
url: url,
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
//do things
}
});
Si el servicio web devuelve una clase, funciona así que no tiene nada que ver con los parámetros de entrada, etc. Solo falla cuando el método web devuelve una tabla de datos (la tabla de datos solo tiene 2 columnas y 2 filas para la prueba que estoy haciendo).
La clase WebService está decorada con el atributo [ScriptService], así que pensé que ASP.NET serializaría automáticamente el valor de retorno como JSON. No parece funcionar con datatable.
La única solución que encontré fue devolver una cadena (un objeto serializado JSON manualmente) pero no me parece correcto hacerlo de esta forma.
Estoy usando Visual Studio 2008 con .Net 3.5
Al final, he decidido usar la clase JavaScriptSerializer para convertir DataTable en una cadena JSON. Desafortunadamente, esta clase no funciona con una DataTable, así que convertí la DataTable en una lista de dictionnaries y pasé esa lista a la clase JavaScriptSerializer. Solo requiere unas pocas líneas de código y funciona bien.
Ejemplo en VB.net:
Public Function GetJson(ByVal dt As DataTable) As String
Dim serializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer()
Dim rows As New List(Of Dictionary(Of String, Object))
Dim row As Dictionary(Of String, Object)
For Each dr As DataRow In dt.Rows
row = New Dictionary(Of String, Object)
For Each col As DataColumn In dt.Columns
row.Add(col.ColumnName, dr(col))
Next
rows.Add(row)
Next
Return serializer.Serialize(rows)
End Function
Al igual que Marc, tampoco me sorprende que DataTable rompa su intercambio de servicio web / json. Me gustaría respaldar a Json.NET también.
Pero si decides no seguir adelante, aún no tienes que compilar el json manualmente. Simplemente haga su propia clase personalizada con todas las propiedades que necesita y luego devuelva una matriz de esa clase. Por supuesto, tendrá que escribir un código para "convertir" su tabla de datos en su nueva clase. Lo sé, podría ser una gran cantidad de escritura de código, pero es mucho menos propenso a errores y luego tratar de hacer manualmente una cadena json.
La forma más sencilla es usar el LINQ para las extensiones de DataSet. Primero necesita crear una lista genérica (SearchSerialResults es solo una DTO en este caso) desde DataTable usando LINQ to DataSet.
var resultItems = (from DataRow dr in _returnedData.AsEnumerable()
select new SearchSerialResults
{
ContractLineItem = (int)dr["fldContractLineItemID"],
SearchItem = (string)dr["Search Item"],
Customer = (string)dr["Customer"],
DeviceFound = (string)dr["Device Found"],
Country = (string)dr["Country"],
City = (string)dr["City"],
ContractNumber = (string)dr["Contract Number"],
QuoteNumber = (string)dr["Quote Number"],
BeginDate = (string)dr["Begin Date"],
EndDate = (string)dr["End Date"]
}).ToList();
_returnedData es la DataTable en este caso. El paso 2 es hacer la conversión. En este caso, estoy devolviendo un objeto Json para un jqGrid.
var jsonObject = new
{
total = totalPages,
pageSize,
records = totalRecords,
rows = (from SearchSerialResults item in resultItems
select new
{
id = item.ContractLineItem,
cell = new[]
{
item.ContractLineItem.ToString(),
item.SearchItem,
item.DeviceFound,
item.Customer,
item.ContractNumber,
item.QuoteNumber,
item.Country,
item.City,
item.BeginDate,
item.EndDate,
""
}
}).ToArray()
};
return Json(jsonObject) // for MVC
Encontré esta clase de C # muy útil:
[Serializable]
public class TableMethod
{
private int m_total; public int total { get { return this.m_total; } set { this.m_total = value; } }
private int m_page; public int page { get { return this.m_page; } set { this.m_page = value; } }
private int m_records; public int records { get { return this.m_records; } set { this.m_records = value; } }
private IList<RowElement> m_rows; public IList<RowElement> rows { get { return this.m_rows; } set { this.m_rows = value; } }
public TableMethod()
{
this.m_records = 20;
this.m_total = 20;
this.m_page = 1;
}
}
[Serializable]
public class RowElement
{
public string id;
public string[] cell;
}
Me funciona muy bien con un WebService
Imports System.Web.Script.Serialization
Dim wsServicio As New ["YourWsInstance"]
Dim dsInstEstado As New DataSet
Dim sSql As String
sSql = " Your SQL Statement"
dsInstEstado = wsServicio.getData("YourWebServiceParameters")
Dim jsonString = DataTableToJSON(dsInstEstado.Tables("CA_INSTITUCION"))
Return Json(jsonString, JsonRequestBehavior.AllowGet)
Function DataTableToJSon(dt As DataTable) As Object
Dim arr(dt.Rows.Count - 1) As Object
Dim column As DataColumn
For i = 0 To dt.Rows.Count - 1
Dim dict As New Dictionary(Of String, Object)
For Each column In dt.Columns
dict.Add(column.ColumnName, dt.Rows(i)(column))
Next
arr(i) = dict
Next
Return arr
End Function
.Net 3.5 tiene un JSONSerializer que debería poder manejar una tabla de datos. Es posible que desee revisar su código de servicio nuevamente e intentar que lo use. Además, puse un código para hacerlo manualmente en esta pregunta.
Debo admitir que no estoy muy sorprendido: DataTable
básicamente rompe la mayoría de las reglas de datos estructurados. ¿Por qué no simplemente proyectar desde la tabla de datos a un objeto tipado? Una pregunta relacionada surgió antes ... o si conoce el esquema de DataTable
simplemente haga la conversión en C # ...
Construir manualmente el JSON podría funcionar, pero hay muchos casos extremos que evitar; Prefiero dejar que un marco existente lo maneje, para ser honesto.