使用Fetch向MVC控制器传值失败:控制器接收空对象问题排查
使用Fetch API向MVC控制器传数据时接收为空的解决方法
问题场景
用原生JavaScript的Fetch API向MVC控制器发送POST请求,浏览器中可见的请求Payload格式正常,但控制器接收的ImportInvoiceIncoming实体类所有属性均为默认值(null、0、false等)。
相关代码
前端Fetch代码
fetch( '/InvoiceIncoming/SaveCsvInvoiceToDb', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: csvRows[j] // 尝试过JSON.stringify(csvRows[j])也无效 }) .then(function (response) { console.log(response); return response.json(); }) .then(function (data) { console.log(data); }).catch(function (err) { console.warn('请求失败', err); });
后端控制器代码
public ActionResult SaveCsvInvoiceToDb(ImportInvoiceIncoming csvInvInc) { return Json("ok"); }
请求Payload(浏览器中可见)
{ "ConstructionSite":null, "InvoiceIncoming":null, "CsvAmountGross":"70,73", "AmountGross":0, "CostCenterNumber":"H0040000", "CsvDueDate":"06.09.2023", "DueDate":"2023-09-06T02:00:00+02:00", "InvoiceDatevId":"5B86985A-9EC9-DEF9-665C-72ED614E07BA", "CsvInvoiceDate":"07.08.2023", "CsvVatKey":"94", "InvoiceDate":"2023-08-07T02:00:00+02:00", "InvoiceNumber":"E01000GNRF", "Paid":null, "SupplierName":"supplierino", "SupplierVatId":"numberino", "Supplier":null, "Vat":{ "DUssId":1, "OUmsatzsteuersatz":0, "DGueltigVon":"2011-12-24T00:00:00", "DGueltigBis":"9999-12-31T00:00:00", "DAngelegtAm":"2011-12-24T10:00:26.897", "DAngelegtVonFk":-2, "DLetzteAenderungAm":"2011-12-24T10:00:26.897", "DLetzteAenderungVonFk":-2, "VatRateText":"0,00" }, "HasConvertedDueDate":true, "HasConvertedInvoiceDate":true, "HasConvertedAmountGross":false, "HasValidVatRate":true, "CostCenterMatches":false, "DateMatches":false, "AmountGrossMatches":false, "SelectedForImport":true }
控制器接收结果
csvInvInc {ImportInvoiceIncoming} AmountGross: 0 AmountGrossMatches: false ConstructionSite: null CostCenterMatches: false CostCenterNumber: null CsvAmountGross: null CsvDueDate: null CsvInvoiceDate: null CsvVatKey: null DateMatches: false DueDate: {01.01.0001 00:00:00} HasConvertedAmountGross: false HasConvertedDueDate: false HasConvertedInvoiceDate: false HasValidVatRate: false InvoiceDate: {01.01.0001 00:00:00} InvoiceDatevId: null InvoiceIncoming: null InvoiceNumber: null Paid: null SelectedForImport: false Supplier: null SupplierName: null SupplierVatId: null Vat: null amountGross: 0 csvDueDate: null csvInvoiceDate: null cu: {de-DE}
解决步骤
1. 强制添加[FromBody]特性
MVC默认从表单数据(application/x-www-form-urlencoded)绑定参数,而你的请求是JSON格式,必须显式告诉控制器从请求体读取数据。修改控制器方法:
public ActionResult SaveCsvInvoiceToDb([FromBody] ImportInvoiceIncoming csvInvInc) { return Json("ok"); }
2. 确保请求体正确序列化
必须用JSON.stringify()将JavaScript对象转换为JSON字符串,否则请求体格式不合法。修改前端代码的body部分:
body: JSON.stringify(csvRows[j])
确认csvRows[j]是合法的JavaScript对象,而非已序列化的字符串。
3. 检查实体类属性配置
确保ImportInvoiceIncoming类的所有属性为public且带有get/set访问器,属性名与JSON键完全匹配(MVC默认支持驼峰与帕斯卡命名自动映射,但拼写错误会导致绑定失败)。示例:
public class ImportInvoiceIncoming { public string ConstructionSite { get; set; } public string CsvAmountGross { get; set; } public decimal AmountGross { get; set; } // 其他属性... public Vat Vat { get; set; } // 确保嵌套类Vat也有public属性和get/set } public class Vat { public int DUssId { get; set; } // 其他属性... }
4. 验证请求头与格式
通过浏览器开发者工具的Network标签,确认请求头的Content-Type确实为application/json,避免被其他代码覆盖。
5. 调试请求体
若以上步骤无效,可在控制器中直接读取原始请求体,验证是否接收到正确的JSON:
using (var reader = new StreamReader(Request.InputStream)) { string rawBody = reader.ReadToEnd(); // 输出rawBody到日志或调试窗口,对比浏览器中的Payload }
内容的提问来源于stack exchange,提问作者Mister 832
相关产品推荐
相关产品推荐

