.Net Core 6中DateTimeOffset无法从HTTP请求绑定到视图模型
.NET Core 6 Web API DateTimeOffset 偏移量丢失问题解决方案
问题分析
你遇到的是DateTimeOffset类型在模型绑定时偏移量未被正确保留的问题。从请求示例来看,传入的是UTC格式时间(2023-05-12T15:52:41.009Z,对应偏移+00:00),若实际需要传入非UTC偏移的时间或绑定后偏移处理不符合预期,可通过以下方案解决:
方案1:配置JSON序列化选项
.NET Core默认使用System.Text.Json,默认解析逻辑虽能处理DateTimeOffset,但显式配置可确保偏移量被严格保留。在Program.cs中添加以下配置:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; // 添加自定义转换器,强制使用ISO 8601往返格式保留偏移 options.JsonSerializerOptions.Converters.Add(new DateTimeOffsetConverter()); }); // 自定义DateTimeOffset转换器 public class DateTimeOffsetConverter : JsonConverter<DateTimeOffset> { public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return DateTimeOffset.TryParse(reader.GetString(), out var result) ? result : DateTimeOffset.UtcNow; } public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("o")); // "o"格式严格保留偏移信息 } }
方案2:修正Swagger的时间格式支持
如果是Swagger UI自动将带偏移的时间转为UTC(Z结尾),可修改Swagger配置,让其支持自定义偏移的DateTimeOffset输入:
builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Market API", Version = "v1" }); // 为DateTimeOffset指定Schema格式,提示输入带偏移的ISO 8601时间 c.MapType<DateTimeOffset>(() => new OpenApiSchema { Type = "string", Format = "date-time-offset", Example = new OpenApiString(DateTimeOffset.Now.ToString("o")) }); });
配置后Swagger UI会提示输入类似2023-05-12T15:52:41.009+08:00的带偏移格式,而非强制转为UTC。
方案3:检查视图模型字段定义
确保视图模型的StartPeriod字段未被错误特性修饰:
public class SetMarkingInvestmenViewModel { [Required] public decimal Investment { get; set; } [Required] // 避免添加会干扰偏移处理的特性(如[DataType(DataType.DateTime)]) public DateTimeOffset StartPeriod { get; set; } }
方案4:调试原始请求内容
若以上方案无效,可在控制器中读取原始请求体,确认是否是前端(Swagger)传入的格式本身丢失了偏移:
[HttpPost("set-investment")] public IActionResult SetMarketingInvestment([FromBody] SetMarkingInvestmenViewModel model) { // 读取原始请求内容 Request.Body.Position = 0; using var reader = new StreamReader(Request.Body); var rawRequestBody = reader.ReadToEnd(); // 输出到控制台或日志,验证传入的StartPeriod格式 Console.WriteLine(rawRequestBody); // 业务逻辑 return Ok(model); }
内容的提问来源于stack exchange,提问作者Antoine a.k.a Zesso Renoux
相关产品推荐
相关产品推荐

