You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; }

验证步骤

  1. 使用抓包工具(如Charles)确认请求中确实包含BirthDate字段,且格式符合服务端预期。
  2. 查看服务端调试日志,确认字段是否被正确识别并绑定。

内容的提问来源于stack exchange,提问作者N.T. Dang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:18:21