我正在尝试使用以下代码执行返回DataTable的Web服务:
$.ajax({
type: "POST",
url: url,
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
//do things
}
});
如果webservice返回一个类,那么它就可以工作,因此它与输入参数等无关。它只在web方法返回一个数据表时失败(数据表只有2列和2行用于测试我是这样做)。
WebService类使用[ScriptService]属性进行修饰,因此我认为ASP.NET会自动将返回值序列化为JSON。它似乎不适用于数据表。
我找到的唯一解决方案是返回一个字符串(一个手动JSON序列化对象),但我这样做是不对的。
我正在使用Visual Studio 2008和.Net 3.5
答案 0 :(得分:8)
最后,我决定使用JavaScriptSerializer类将DataTable转换为JSON字符串。 不幸的是,这个类不适用于DataTable,所以我将DataTable转换为dictionnaries列表并将该列表传递给JavaScriptSerializer类。它只需几行代码即可正常工作 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
答案 1 :(得分:5)
最简单的方法是使用LINQ to DataSet扩展。首先需要使用LINQ to DataSet从DataTable创建一个通用列表(在这种情况下,SearchSerialResults只是一个DTO)。
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是DataTable。第2步是进行转换。在这种情况下,我将为jqGrid返回一个Json对象。
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
答案 2 :(得分:4)
Json.NET能够将DataSets / DataTables写入JSON。
http://james.newtonking.com/archive/2008/09/06/dataset-datatable-serialization-with-json-net.aspx
答案 3 :(得分:4)
答案 4 :(得分:2)
对于使用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
答案 5 :(得分:1)
我必须承认我并不是非常惊讶 - DataTable
基本上打破了结构化数据的大多数规则。为什么不简单地从数据表投射到类型化对象?之前出现related question ...或者如果您知道DataTable
的架构只是在C#中进行转换......
手动构建JSON可能会起作用,但是有很多边缘情况需要避免;老实说,我宁愿让现有的框架处理它。
答案 6 :(得分:0)
.Net 3.5有一个JSONSerializer,应该能够处理数据表。您可能希望再次查看服务代码并尝试使用它。另外,我将一些代码放在一起,在this question.
中手动完成答案 7 :(得分:0)
和Marc一样,DataTable破坏了你的webservice / json交换,我也不会感到惊讶。我也想赞同Json.NET。
但是如果你决定不使用它,你仍然不必手动构建json。只需使用您需要的所有属性创建自己的精简自定义类,然后返回该类的数组。您当然必须编写代码以将数据表“转换”为新类。我知道,这可能是很多代码编写,但是它更容易出错,然后尝试手动创建一个json字符串。
答案 8 :(得分:0)
我发现这个C#类非常有用:
[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;
}