阅读了大量不同的解决方案并尝试了不同的方法(here,here,here,here,here),我得到了来自API控制器的不同(和意外)结果。
我需要通过web api控制器返回表示为JSON的数据表:
[IdentityBasicAuthentication]
[Authorize]
[RequireHttps]
[Route("Reports/Report1")]
public HttpResponseMessage Get()
{
DataTable dt = MyDAL.GetDataTable();
if(someValidationFailed){
Request.CreateResponse(HttpStatusCode.BadRequest, "Friendly error here");
}
return Request.CreateResponse(HttpStatusCode.OK, Newtonsoft.Json.JsonConvert.SerializeObject(dt));
}
在Fiddler中,输出似乎被编码为转义字符串:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
"[{\"Site\":\"Headquarters\",\"Department\":\"HR\",\"FirstName\":\"Bob\",\"MiddleName\":null,\"Surname\":\"Fern\",\"EmployeeNumber\":\"444\"},
{\"Site\":\"Headquarters\",\"Department\":\"HR\",\"FirstName\":\"Alice\",\"MiddleName\":null,\"Surname\":\"Smith\",\"EmployeeNumber\":\"769\"}]"
但是,目标是输出普通的Json(如果客户端请求它,则输出XML):
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
[{"Site":"Headquarters","Department":"HR","FirstName":"Bob","MiddleName":null,"Surname":"Fern","EmployeeNumber":"444"},
{"Site":"Headquarters","Department":"HR","FirstName":"Alice","MiddleName":null,"Surname":"Smith","EmployeeNumber":"769"}]
有没有办法在不创建IEnumerable<Person>
对象的情况下执行此操作?原因是这个类特定于这一个方法。我也不想使用StringBuilder,因为DataTable可能非常大,而且我之前已经看过内存异常。
我是WebAPI的新手,所以答案可能非常简单,但我可以提出进一步问题的代码示例会非常有用。
答案 0 :(得分:9)
Web API为您处理序列化,因此您无需致电JsonConvert.SerializeObject
。这就是为什么你得到一个转义字符串作为输出值。只需将数据表直接传递给CreateResponse
即可。 Web API会根据请求的Accept
标头中发送的内容将其转换为JSON或XML。 (它使用了Json.Net。)
return Request.CreateResponse(HttpStatusCode.OK, dt);
答案 1 :(得分:1)
使用匿名类型。 JSON支持匿名类型的序列化。
var persons = datatable.AsEnumerable()
.Select(datarow => new
{
Site = datarow.Field<string>("Site")
});
return Request.CreateResponse(HttpStatusCode.OK,
Newtonsoft.Json.JsonConvert.SerializeObject(persons));