Angular应用中HTTP PUT请求未更新数据反而新增条目问题排查
问题根本原因
核心是你提交更新的设备实体没有携带主键ID值,EF Core检测到实体主键为默认值时,会将其识别为全新实体,执行新增逻辑而非更新逻辑,具体问题点如下:
- 弹窗组件的更新表单没有包含ID字段:你调用
GetWithId接口拿到了完整的设备数据,但构建响应式表单formG时仅添加了业务字段,没有将主键ID纳入表单,最终提交的equipment对象ID为int类型默认值0 - (可选规范问题)后端PUT接口不符合RESTful设计规范,没有对ID做校验,也没有绑定路由ID参数,无法提前拦截主键缺失的非法请求
修复步骤
1. 前端表单补全ID字段
二选一实现即可:
方案A:提交时手动赋值ID(无需修改表单结构)
修改DialogFormUpdateComponent的SendFormUpdate方法,提交时把已经拿到的ID赋值给实体:
public SendFormUpdate(): void { let newDate: moment.Moment = moment.utc(this.formG.value.date).local(); this.formG.value.date = newDate.format("YYYY-MM-DD"); // 新增代码:手动补上ID const equipment: Equipments = {...this.formG.value, id: this.id }; this.EquipmentService.PutEquipment(equipment).subscribe(result => { alert("Equipment was updated with success"); this.formG.reset(); this.dialogRef.close(); }) }
方案B:表单新增ID控件(适合需要关联校验的场景)
修改ngOnInit中构建表单的代码,加入ID字段(无需渲染到前端页面):
this.formG = this.fb.group({ id: [result.id], name: [result.name, [Validators.required]], serialNumber: [result.serialNumber, [Validators.required]], voltage: [result.voltage, [Validators.required]], electricCurrent: [result.electricCurrent, [Validators.required]], oil: [result.oil, [Validators.required]], date: [result.date, [Validators.required]], });
2. (可选推荐)后端接口优化
修改后端PutEquipmentAsync方法,绑定路由参数并做合法性校验,避免非法请求:
[HttpPut("{id}")] public async Task<ActionResult> PutEquipmentAsync(int id, Equipments equipments) { // 校验路由ID和实体ID是否一致 if (id!= equipments.Id) { return BadRequest("ID不匹配"); } // 校验实体是否存在 var exist = await _ContextEquipment.Equipment.AnyAsync(e => e.Id == id); if (!exist) { return NotFound("设备不存在"); } _ContextEquipment.Equipment.Update(equipments); await _ContextEquipment.SaveChangesAsync(); return Ok(); }
同步修改前端EquipmentsService的PUT请求地址,符合REST规范:
PutEquipment(equipment: Equipments): Observable<any>{ const Url = `${this.url}/${equipment.id}`; return this.http.put<Equipments>(Url, equipment, httpOptions); }
如果修复后仍有问题,请检查Equipments实体类的主键是否添加了[Key]特性,是否配置了正确的主键映射。
内容的提问来源于stack exchange,提问作者Leonardo Moreira
相关产品推荐
相关产品推荐

