React Native向ASP.NET Core API传FormData时可空字段值丢失
React Native Expo 发送multipart/form-data到ASP.NET Core Web API时可空日期字段丢失值问题
问题场景
客户端基于React Native Expo(安卓Expo Go),使用axios以multipart/form-data格式发送更新请求,其中BirthDate字段在有值时已append到FormData,但服务端ASP.NET Core Web API接收模型中的DateTimeOffset? BirthDate始终为null。服务端日志明确提示"Could not find a value in the request with name 'BirthDate'"。
客户端关键代码
// NationalId, Address, Phone, BirthDate均为字符串,BirthDate可能为undefined const formData = new FormData(); formData.append('NationalId', NationalId); formData.append('Address', Address); formData.append('Phone', Phone); if (BirthDate) { formData.append('BirthDate', BirthDate); } if (Image) { formData.append('Image', Image); } const res = await axios.put( `Employees/UpdateSelf/${NationalId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } } );
服务端关键代码
public class UpdateSelfRequest { public string NationalId { get; set; } = string.Empty; public string? Phone { get; set; } public string? Address { get; set; } public DateTimeOffset? BirthDate { get; set; } public IFormFile? Image { get; set; } } [HttpPut("UpdateSelf/{NationalId}")] [Authorize(Roles = AuthRoles.Employee)] [Consumes("multipart/form-data")] public async Task<IActionResult> UpdateSelf( [FromRoute] string NationalId, [FromForm] UpdateSelfRequest req) { // req.BirthDate为null,尽管客户端已传值 var result = await _service.UpdateSelf(NationalId, req); if (!result.Success) { return Forbid(); } return Ok(); }
问题原因及解决方案
原因1:手动设置Content-Type导致boundary缺失
axios发送FormData时会自动生成包含boundary的multipart/form-data请求头,手动设置Content-Type: multipart/form-data会丢失boundary参数,导致服务端无法正确解析表单字段。
解决方法:移除手动设置的headers,让axios自动处理请求头:
const res = await axios.put( `Employees/UpdateSelf/${NationalId}`, formData );
原因2:日期格式不匹配导致绑定失败
ASP.NET Core默认仅支持ISO 8601格式的字符串绑定到DateTimeOffset类型(如2024-05-20T12:34:56+08:00),如果客户端发送的是其他格式(如YYYY-MM-DD),会触发绑定失败,最终表现为字段值为null。
解决方法(客户端)
将日期转换为ISO 8601格式后再append到FormData:
if (BirthDate) { // 假设BirthDate是"YYYY-MM-DD"格式,转换为ISO标准格式 const isoDate = new Date(BirthDate).toISOString(); formData.append('BirthDate', isoDate); }
解决方法(服务端)
配置支持自定义日期格式,无需修改客户端代码:
在Program.cs中添加全局日期格式配置:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonConverter<DateTimeOffset?>() { Read = (reader, typeToConvert, options) => { if (reader.TokenType == System.Text.Json.JsonTokenType.String) { // 优先尝试标准ISO格式 if (DateTimeOffset.TryParse(reader.GetString(), out var date)) { return date; } // 兼容YYYY-MM-DD格式 if (DateTime.TryParse(reader.GetString(), out var dateTime)) { return new DateTimeOffset(dateTime); } } return null; }, Write = (writer, value, options) => { writer.WriteStringValue(value?.ToString("yyyy-MM-ddTHH:mm:sszzz") ?? string.Empty); } }); });
或者直接在模型属性上添加特性指定格式:
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTimeOffset? BirthDate { get; set; }
验证步骤
- 使用抓包工具(如Charles)确认请求中确实包含BirthDate字段,且格式符合服务端预期。
- 查看服务端调试日志,确认字段是否被正确识别并绑定。
内容的提问来源于stack exchange,提问作者N.T. Dang
相关产品推荐
相关产品推荐

