.NET Web API/Blazor中DateTime序列化与反序列化异常排查
Blazor应用无法正常反序列化DateTime的原因及解决办法
问题描述
我希望在Blazor应用中显示服务器时间,当前实现步骤如下:
控制器代码
[HttpGet] public Task<DtoValue<DateTime>> GetServerLocalTime() => Task.FromResult(new DtoValue<DateTime>(DateTime.Now));
对应的DtoValue类
public class DtoValue<T> { public DtoValue() { } public DtoValue(T? value) { Value = value; } public T? Value; }
Program.cs配置
在Program.cs中已添加Newtonsoft配置:
builder.Services.AddControllers() .AddNewtonsoftJson();
Web API返回结果
Web API返回的JSON数据为:
{ "value": "2023-01-16T23:13:53.0037535+01:00" }
异常情况
但在Blazor应用中使用以下代码反序列化时:
var dtoTimeValue = await HttpClient.GetFromJsonAsync<DtoValue<DateTime>>("api/Hello/GetServerLocalTime").ConfigureAwait(false);
得到的dtoTimeValue中DateTime为默认值1/1/0001 12:00:00 AM。
而手动使用Newtonsoft.Json反序列化时则正常:
var result = await HttpClient.GetAsync("api/Hello/GetServerLocalTime").ConfigureAwait(false); var resultString = await result.Content.ReadAsStringAsync().ConfigureAwait(false); var dtoTimeValue = JsonConvert.DeserializeObject<DtoValue<DateTime>>(resultString);
原因分析
核心问题在于序列化/反序列化工具的规则不匹配:
- 后端API使用Newtonsoft.Json(Json.NET)序列化数据,但Blazor中
HttpClient.GetFromJsonAsync默认采用的是System.Text.Json。 DtoValue<T>类中的Value是字段而非属性,System.Text.Json默认仅处理带getter/setter的属性,不会序列化或反序列化字段;而Newtonsoft.Json默认支持字段的序列化/反序列化,这就是两种方式结果不同的直接原因。
解决办法
方案1:将字段改为属性
修改DtoValue<T>类,把Value字段替换为带getter和setter的属性,让System.Text.Json可以识别并处理:
public class DtoValue<T> { public DtoValue() { } public DtoValue(T? value) { Value = value; } public T? Value { get; set; } }
方案2:让HttpClient使用Newtonsoft.Json反序列化
如果不想修改类结构,可以为Blazor的HttpClient封装Newtonsoft.Json的反序列化逻辑:
- 为Blazor项目安装
Newtonsoft.JsonNuGet包。 - 添加自定义扩展方法:
public static class HttpClientExtensions { public static async Task<T?> GetFromNewtonsoftJsonAsync<T>(this HttpClient client, string requestUri) { var response = await client.GetAsync(requestUri).ConfigureAwait(false); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); return JsonConvert.DeserializeObject<T>(content); } }
- 在Blazor中使用该扩展方法替代默认的
GetFromJsonAsync:
var dtoTimeValue = await HttpClient.GetFromNewtonsoftJsonAsync<DtoValue<DateTime>>("api/Hello/GetServerLocalTime").ConfigureAwait(false);
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

