来自 API 的 ResponseStream 在反序列化时产生空值
ResponseStream from API results in empty values on deserializing
从我的 API 返回数据并在客户端控制器中反序列化它,内容似乎是空的。我已验证 API 正在返回有效数据,并且响应中的“计数”是准确的。但是,序列化时的数据好像没有初始化。
不太确定在哪里寻找导致问题的原因。我最好的理论是数据在由于异步而具体化之前被反序列化,但这并不能解释为什么计数是正确的(2 条记录)。
public async Task<IActionResult> Index()
{
var httpClient = _httpClientFactory.CreateClient("APIClient");
var request = new HttpRequestMessage(HttpMethod.Get, "/api/AppUsers");
var response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
using (var responseStream = await response.Content.ReadAsStreamAsync())
{
var users = await JsonSerializer.DeserializeAsync<IList<AppUser>>(responseStream);
return View(new IndexViewModel(users));
}
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized ||
response.StatusCode == System.Net.HttpStatusCode.Forbidden)
{
return RedirectToAction("AccessDenied", "Authorization");
}
throw new Exception("Problem accessing the API");
}
API 调用的方法
[HttpGet]
public IActionResult GetAppUsers()
{
var users = _appUserService.ListAppUsers();
return Ok(users);
}
调用API方法直接显示如预期返回的2行
经过一些调试,我注意到从 API 返回的 json 结构的 属性 名称中的第一个字母是小写的,但是 AppUser class 有首字母大写。不知道为什么会这样,但这就是反序列化失败的原因。
尝试反序列化为 List 而不是 IList:
var users = await JsonSerializer.DeserializeAsync<List<AppUser>>(responseStream);
我认为您应该删除 ConfigureAwait(false) 以便您可以保持在相同的同步上下文中。
有关更多信息,请查看此 link:https://devblogs.microsoft.com/dotnet/configureawait-faq/
注意到 JSON 对象的属性从大写变为小写后,解决方案是将 JSON 强制为 PascalCase,因为现在默认为驼峰式
https://codeopinion.com/asp-net-core-mvc-json-output-camelcase-pascalcase/
或者我需要考虑反序列化时的驼峰命名法。
这个问题偷走了我几个小时的生活:/
希望这个 post 可以为其他人节省一些时间。
一种解决方案是禁用默认设置
builder.Services.AddControllers(options =>
{
options.ReturnHttpNotAcceptable = true;
})
.AddXmlSerializerFormatters()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null; //to avoid defaulting to camelCase
});
从我的 API 返回数据并在客户端控制器中反序列化它,内容似乎是空的。我已验证 API 正在返回有效数据,并且响应中的“计数”是准确的。但是,序列化时的数据好像没有初始化。
不太确定在哪里寻找导致问题的原因。我最好的理论是数据在由于异步而具体化之前被反序列化,但这并不能解释为什么计数是正确的(2 条记录)。
public async Task<IActionResult> Index()
{
var httpClient = _httpClientFactory.CreateClient("APIClient");
var request = new HttpRequestMessage(HttpMethod.Get, "/api/AppUsers");
var response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
using (var responseStream = await response.Content.ReadAsStreamAsync())
{
var users = await JsonSerializer.DeserializeAsync<IList<AppUser>>(responseStream);
return View(new IndexViewModel(users));
}
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized ||
response.StatusCode == System.Net.HttpStatusCode.Forbidden)
{
return RedirectToAction("AccessDenied", "Authorization");
}
throw new Exception("Problem accessing the API");
}
API 调用的方法
[HttpGet]
public IActionResult GetAppUsers()
{
var users = _appUserService.ListAppUsers();
return Ok(users);
}
调用API方法直接显示如预期返回的2行
经过一些调试,我注意到从 API 返回的 json 结构的 属性 名称中的第一个字母是小写的,但是 AppUser class 有首字母大写。不知道为什么会这样,但这就是反序列化失败的原因。
尝试反序列化为 List 而不是 IList:
var users = await JsonSerializer.DeserializeAsync<List<AppUser>>(responseStream);
我认为您应该删除 ConfigureAwait(false) 以便您可以保持在相同的同步上下文中。
有关更多信息,请查看此 link:https://devblogs.microsoft.com/dotnet/configureawait-faq/
注意到 JSON 对象的属性从大写变为小写后,解决方案是将 JSON 强制为 PascalCase,因为现在默认为驼峰式
https://codeopinion.com/asp-net-core-mvc-json-output-camelcase-pascalcase/
或者我需要考虑反序列化时的驼峰命名法。
这个问题偷走了我几个小时的生活:/ 希望这个 post 可以为其他人节省一些时间。
一种解决方案是禁用默认设置
builder.Services.AddControllers(options =>
{
options.ReturnHttpNotAcceptable = true;
})
.AddXmlSerializerFormatters()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null; //to avoid defaulting to camelCase
});