React调用.NET API向SQL Server传数据报400错误求助
400 Bad Request 问题排查与解决方案
核心原因分析
Swagger能正常调用接口但前端请求返回400,本质是前端请求格式/参数与后端接收规则不匹配,常见触发点包括:
- 请求
Content-Type与后端接收注解([FromForm]/[FromBody])不匹配 - 前端提交的字段名与后端模型属性名不一致(大小写、拼写错误)
- 后端模型标记
[Required]的必填字段前端未传值 - JSON序列化/反序列化时格式错误
针对两种前端提交方式的修正方案
1. 无JSON转换的FormData提交(适用于带文件上传的场景)
如果后端接口用[FromForm]接收表单数据,前端需直接传递FormData,并正确设置请求头:
前端修正代码
import axios from 'axios'; const submitData = async (formValues) => { const formData = new FormData(); // 注意:字段名需与后端模型属性名完全一致(区分大小写) formData.append('Name', formValues.name); formData.append('Age', formValues.age); // 若有文件,直接追加文件对象 // formData.append('Attachment', formValues.file); try { const response = await axios.post('/api/your-endpoint', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); console.log('提交成功:', response.data); } catch (err) { console.error('提交失败:', err.response); } };
对应后端代码(需确保用[FromForm])
[HttpPost] public IActionResult SubmitData([FromForm] YourDataModel model) { if (!ModelState.IsValid) { // 打印校验错误,方便排查 var errors = ModelState.SelectMany(x => x.Value.Errors).Select(e => e.ErrorMessage); return BadRequest(errors); } // 数据库写入逻辑 return Ok(); }
2. 带JSON转换的FormData提交(不推荐,除非特殊场景)
如果后端需要从FormData中读取JSON字符串,需确保键名与后端接收的参数名一致,同时后端要手动反序列化:
前端修正代码
const submitData = async (formValues) => { const formData = new FormData(); // 键名需与后端参数名一致,比如后端用model接收 formData.append('model', JSON.stringify({ Name: formValues.name, Age: formValues.age })); try { const response = await axios.post('/api/your-endpoint', formData); console.log('提交成功:', response.data); } catch (err) { console.error('提交失败:', err.response); } };
对应后端代码
[HttpPost] public IActionResult SubmitData([FromForm] string model) { if (string.IsNullOrEmpty(model)) { return BadRequest("模型数据不能为空"); } var dataModel = JsonSerializer.Deserialize<YourDataModel>(model); if (!ModelState.IsValid) { var errors = ModelState.SelectMany(x => x.Value.Errors).Select(e => e.ErrorMessage); return BadRequest(errors); } // 数据库写入逻辑 return Ok(); }
更简洁的替代方案:直接提交JSON(无文件上传场景优先用)
如果没有文件上传需求,无需使用FormData,直接发送JSON格式数据,匹配后端[FromBody]注解:
前端代码
const submitData = async (formValues) => { const data = { Name: formValues.name, Age: formValues.age }; try { const response = await axios.post('/api/your-endpoint', data, { headers: { 'Content-Type': 'application/json' } }); console.log('提交成功:', response.data); } catch (err) { console.error('提交失败:', err.response); } };
对应后端代码
[HttpPost] public IActionResult SubmitData([FromBody] YourDataModel model) { if (!ModelState.IsValid) { var errors = ModelState.SelectMany(x => x.Value.Errors).Select(e => e.ErrorMessage); return BadRequest(errors); } // 数据库写入逻辑 return Ok(); }
快速排查步骤
- 打开浏览器开发者工具→Network面板,查看请求的
Content-Type和Payload是否与Swagger一致 - 检查后端模型的
[Required]字段,确认前端都传了有效值 - 统一字段名大小写:若后端用PascalCase(如
Name),前端需对应;若要支持前端camelCase,可在后端配置JSON序列化:
// Program.cs builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; });
后续下载功能对接手机文件存储
后端下载接口实现
[HttpGet("download/{id}")] public IActionResult DownloadFile(int id) { // 从数据库获取文件数据(示例) var fileRecord = _dbContext.FileRecords.Find(id); if (fileRecord == null) { return NotFound(); } // 返回文件流,指定Content-Type和下载文件名 return File(fileRecord.FileContent, fileRecord.ContentType, fileRecord.FileName); }
前端(React Native)对接手机存储
使用react-native-fs库实现文件保存:
import RNFS from 'react-native-fs'; const downloadToPhone = async (fileId) => { const apiUrl = `https://your-api-domain/api/files/download/${fileId}`; // 保存到手机文档目录 const savePath = `${RNFS.DocumentDirectoryPath}/${fileId}.pdf`; try { const result = await RNFS.downloadFile({ fromUrl: apiUrl, toFile: savePath }).promise; if (result.statusCode === 200) { console.log('文件已保存到:', savePath); // 可调用原生API打开文件或通知用户 } } catch (err) { console.error('下载失败:', err); } };
内容的提问来源于stack exchange,提问作者Sim
相关产品推荐
相关产品推荐

