发送JSON数据时遭遇400 Bad Request问题求助
问题描述
我尝试向API发送JSON数据,但无法成功送达:
- 数据是对象列表,第一次发送空数组时成功
- 第二次发送非空数组直接返回400状态码,调试器根本没进入控制器
- 怀疑是JSON反序列化失败(返回
application/problem+json类型响应),但也不排除其他可能 - 已尝试的方案:使用
[FromBody]特性、切换内置JSON序列化器/Newtonsoft序列化器、添加Formatting.Indented,均无效 - 怀疑对象中存储物理目录路径的字符串参数导致问题,该参数包含
/、\、空格及其他特殊字符
客户端代码
using (HttpClient client = new HttpClient()) { var message = new HttpRequestMessage(); message.Content = JsonContent.Create(files, typeof(List<WatchedFile>)); message.RequestUri = new Uri("http://localhost:5245/api/fileagent"); message.Method = HttpMethod.Post; var response = await client.SendAsync(message); if (!response.IsSuccessStatusCode) { logger.LogError($"Sending to api was not successful {(int)response.StatusCode}"); } }
注:这段代码待重构,计划改为注入HttpClient而非直接使用using语句
控制器代码
[HttpPost] public async Task<ActionResult> AddMessages([FromBody]List<WatchedFile> messages) { messages.ForEach(x => x.Ipaddress = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString()); //send to repository await context.WatchedFiles.AddRangeAsync(messages); await context.SaveChangesAsync(); return Ok(); }
解决步骤
先获取详细错误信息
400错误的application/problem+json响应包含具体错误细节,不要只打印状态码,把响应内容读出来:if (!response.IsSuccessStatusCode) { var errorContent = await response.Content.ReadAsStringAsync(); logger.LogError($"API请求失败,状态码:{(int)response.StatusCode},错误详情:{errorContent}"); }这一步能直接定位反序列化失败的具体字段,比如路径字符串的转义问题,或者
WatchedFile类的属性与JSON字段不匹配。检查
WatchedFile类定义
确保类的属性与序列化后的JSON字段完全匹配:- 所有需要序列化的属性是否为public?
- 是否存在需要特殊处理的类型(如日期、枚举)?
- 存储路径的属性是否标记了正确的序列化特性?比如用System.Text.Json时,是否需要
[JsonPropertyName]匹配字段名?
验证路径字符串的序列化结果
物理路径里的\在JSON中需转义为\\,正常序列化器会自动处理。可以先将files序列化为字符串打印,确认格式是否正确:var jsonStr = JsonSerializer.Serialize(files, new JsonSerializerOptions { WriteIndented = true }); logger.LogInformation("待发送JSON:{JsonStr}", jsonStr);如果发现路径未正确转义或存在非法字符,可手动处理(如替换非法字符,或调整序列化器配置)。
替换JsonContent创建方式
改用StringContent手动序列化,明确指定编码和媒体类型,排除JsonContent.Create的隐式配置问题:var jsonStr = JsonSerializer.Serialize(files); message.Content = new StringContent(jsonStr, Encoding.UTF8, "application/json");检查控制器模型验证配置
调试器未进入控制器,大概率是模型绑定失败。可在Program.cs中配置序列化器和模型验证:builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.AllowTrailingCommas = true; options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; });
内容的提问来源于stack exchange,提问作者technologyresearcher
相关产品推荐
相关产品推荐

