ASP.NET Core MVC表单数组JSON反序列化失败问题求助
问题原因
后端LocationServiceEditDto中的LocationServicePrices是ICollection<LocationServicePriceDto>集合类型,但前端提交的JSON里,该字段是一个键为"0.PricePerUnit"这类字符串的对象,而非数组结构。JSON对象无法直接反序列化为集合类型,因此触发反序列化错误。
解决步骤
1. 修正视图的集合渲染逻辑(改用for循环)
ASP.NET Core模型绑定对集合的识别依赖索引化的name属性,foreach循环无法自动生成符合规范的绑定结构,建议改用for循环(需先将ICollection转为List):
@{ var tierList = Model.LocationServicePrices.ToList(); } @for (int i = 0; i < tierList.Count; i++) { <div class="form-group"> <label>@tierList[i].PricingTierName</label> <!-- 隐藏域传递层级ID,后端需该字段识别对应层级 --> <input type="hidden" asp-for="@tierList[i].PricingTierId" /> <!-- 隐藏域传递关联ID(更新现有数据时需要) --> <input type="hidden" asp-for="@tierList[i].LocationServiceId" /> <!-- 价格输入框,由asp-for自动生成正确的name属性 --> <input class="form-control" type="text" asp-for="@tierList[i].PricePerUnit" data-rule-number="true" data-rule-min="0" data-rule-max="@AppConsts.MaxDecimalDatabaseLength"> </div> }
这里移除了手动指定的name,让asp-for自动生成LocationServicePrices[i].PricePerUnit这类符合模型绑定规范的属性名,同时补充必要的隐藏字段,确保后端能获取完整的LocationServicePriceDto数据。
2. 调整前端序列化逻辑,生成正确的数组结构
如果原serializeFormToObject方法无法解析索引式name,可手动处理表单数据,将其转换为数组结构:
this.save = function() { if (!_$form.valid()) { _$form.showValidateMessage(); return; } // 手动解析表单数据为正确的对象结构 var formData = _$form.serializeArray(); var servicePrice = {}; var locationServicePrices = []; formData.forEach(function(item) { var nameParts = item.name.split('.'); // 处理集合类型字段 if (nameParts[0] === 'LocationServicePrices') { var index = parseInt(nameParts[1].replace(/\[|\]/g, '')); var fieldName = nameParts[2]; if (!locationServicePrices[index]) { locationServicePrices[index] = {}; } locationServicePrices[index][fieldName] = item.value; } else { // 处理普通字段 servicePrice[item.name] = item.value; } }); servicePrice.LocationServicePrices = locationServicePrices; console.log(servicePrice); _modalManager.setBusy(true); _serviceService.editLocationService(servicePrice).done(function() { abp.notify.info('Saved successfully.'); _modalManager.close(); abp.event.trigger('app.createOrEditServicePriceModalSaved'); }).always(function() { _modalManager.setBusy(false); }); };
调整后生成的JSON结构会变为:
{ "Id": "", "ServiceId": "2031", "LocationId": "2", "MaterialUomId": "6", "Cost": "123", "LocationServicePrices": [ {"PricingTierId": "xxx", "LocationServiceId": "xxx", "PricePerUnit": "1"}, {"PricingTierId": "xxx", "LocationServiceId": "xxx", "PricePerUnit": "2"}, ... ] }
3. 确保后端Dto字段匹配
验证LocationServicePriceDto包含前端传递的所有字段,避免反序列化时丢失数据:
public class LocationServicePriceDto { public int? LocationServiceId { get; set; } public int PricingTierId { get; set; } public decimal PricePerUnit { get; set; } // 其他业务所需字段... }
额外说明
- 若使用ABP框架,若自带的
serializeFormToObject仍无法正确解析,直接替换为上述手动处理逻辑即可。 - 后端控制器代码无需修改,只要前端传递的JSON结构正确,ASP.NET Core模型绑定会自动将数组反序列化为
ICollection<LocationServicePriceDto>。
内容的提问来源于stack exchange,提问作者Eugene Sukh
相关产品推荐
相关产品推荐

