【问题标题】:HTTP PUT is creating instead of updating in Angular appHTTP PUT 正在创建而不是在 Angular 应用程序中更新
【发布时间】:2021-11-07 07:31:34
【问题描述】:

我正在使用 Angular 开发一个简单的 CRUD 应用程序,当我提交更新表格元素的表单时,它会创建另一个元素而不是更新相同的元素。怎么了?

服务类:

export class EquipmentsService {
  url = "https://localhost:5001/api/Equipment";
  constructor(private http: HttpClient) { }

   Getall(): Observable<Equipments[]>{
    return this.http.get<Equipments[]>(this.url);
  }


  GetWithId(EquipmentsID: number): Observable<Equipments>
  {
    const Url = `${this.url}/${EquipmentsID}`;
    return this.http.get<Equipments>(Url);
  }
  PostEquipment(equipment: Equipments ): Observable<any>{
    return this.http.post<Equipments>(this.url, equipment, httpOptions);
  }
  PutEquipment(equipment: Equipments): Observable<any>{
    return this.http.put<Equipments>(this.url, equipment,httpOptions);
  }

  DeleteEquipment(equipmentId: number): Observable<any>
  {
    const Url = `${this.url}/${equipmentId}`;
    return this.http.delete<Number>(Url, httpOptions);
  }
}

对话框组件:

export class DialogFormUpdateComponent implements OnInit {

  public titleForm!: string;
  formG!: FormGroup;
  equip!: Equipments;
  id!: number;


  constructor(public dialogRef: MatDialogRef<DialogFormUpdateComponent>, private fb: FormBuilder,
    private EquipmentService: EquipmentsService) {

  }

  ngOnInit(): void {

      console.log(this.id); // It's receiving Id value

      this.EquipmentService.GetWithId(this.id).subscribe(result => {
        this.titleForm = "Update Equipment";
        this.formG = this.fb.group({
          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]],
        });
      });

  }

  public SendFormUpdate(): void {

    let newDate: moment.Moment = moment.utc(this.formG.value.date).local();
    this.formG.value.date = newDate.format("YYYY-MM-DD");
    const equipment: Equipments = this.formG.value;

    this.EquipmentService.PutEquipment(equipment).subscribe(result => {

      alert("Equipment was updated with success");
      this.formG.reset();
      this.dialogRef.close();
    })
  }

  Cancel() {

    this.dialogRef.close();
    this.formG.reset();

  }
}

设备组件:

export class EquipmentsComponent implements OnInit {
  ELEMENT_DATA!: Equipments[];
  form: any;
  titleForm!: string;
  displayedColumns: string[] = ['name', 'serialNumber', 'voltage', 'electricCurrent', 'oil', 'date', 'actions'];
  @Output() equipID: EventEmitter<number>= new EventEmitter<number>();


  public dataSource = new MatTableDataSource<Equipments>(this.ELEMENT_DATA);

  constructor(private EquipmentService: EquipmentsService, public dialog: MatDialog,
    public DialogUpate: MatDialog, public DialogComponentUpdate: DialogFormUpdateComponent) { }

  ngOnInit(): void {

    //getall on start
      this.EquipmentService.Getall().subscribe(result => {
      this.dataSource.data = result as Equipments[];
    });
  }

  //Open Create Form
  NewEquipemnt(): void {
    const dialogRef = this.dialog.open(DialogFormComponent,{
      minWidth: '300px', disableClose: true

    });

    dialogRef.afterClosed().subscribe(result => {
      console.log('The dialog was closed');
      //get all
      this.EquipmentService.Getall().subscribe(result => {
        this.dataSource.data = result as Equipments[];
        });
    });
  }

  //Open Update Form
  public UpdateEquipment(EquipId:  number): void
  {

    const dialogRef = this.DialogUpate.open(DialogFormUpdateComponent,{
      minWidth: '300px', disableClose: true,
    });

    dialogRef.componentInstance.id = EquipId;
    dialogRef.afterClosed().subscribe(result => {
      console.log('The dialog was closed');
        //get all
        this.EquipmentService.Getall().subscribe(result => {
        this.dataSource.data = result as Equipments[];
        });
    });

  }


}

我的更新按钮获取元素的数据将被更新,但是当我点击提交时会在我的数据库中创建其他元素

设备控制器:

namespace TreeApi.Controllers
{
    [ApiController]
    [Route("Api/[Controller]")]
    public class EquipmentController : ControllerBase
    {
        private readonly ContextEquipment _ContextEquipment;

        public EquipmentController (ContextEquipment context)
        {
            _ContextEquipment = context;
        }

        [HttpGet]
        public async Task<ActionResult<IEnumerable<Equipments>>> GetAllAsync()
        {
         return await _ContextEquipment.Equipment.ToListAsync();
        }

        [HttpGet("{EquipmentsID}")]
        public async Task<ActionResult<Equipments>> GetEquipmentAsync(int EquipmentsID)
        {
            Equipments equipment = await _ContextEquipment.Equipment.FindAsync(EquipmentsID);

            if(equipment == null)
            {
                return NotFound();
            }

            return equipment;
        }

        [HttpPost]
        public async Task<ActionResult<Equipments>> PostEquipmentAsync(Equipments equipments)
        {   
            await _ContextEquipment.Equipment.AddAsync(equipments);
            await _ContextEquipment.SaveChangesAsync();

            return Ok();
        }
        [HttpPut]
        public async Task<ActionResult> PutEquipmentAsync(Equipments equipments)
        {
            _ContextEquipment.Equipment.Update(equipments);
            await _ContextEquipment.SaveChangesAsync();

            return Ok();

        }

        [HttpDelete("{EquipmentsID}")]
        public async Task<ActionResult> DeleteEquipmentAsync(int EquipmentsID)
        {
           Equipments equipment = await _ContextEquipment.Equipment.FindAsync(EquipmentsID);
            _ContextEquipment.Remove(equipment);
            await _ContextEquipment.SaveChangesAsync();

            return Ok();
        }
    }
}

启动:

namespace TreeApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddDbContext<ContextEquipment>(options => options.UseSqlServer
                (Configuration.GetConnectionString("ConnectionDB")));
            services.AddCors();
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseHttpsRedirection();
    
            app.UseRouting();
            app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

【问题讨论】:

  • 问题出在您的 API 中。您可以添加设备端点的代码吗?它显然以某种方式选择了错误的路线/方法。
  • @JimJimson 是的,当然。我现在确实添加了。

标签: angular asp.net-core http web-applications asp.net-core-webapi


【解决方案1】:

关注

在您的SendFormUpdate 方法中,您错过了分配id,这是equipment 的主键。

DialogFormUpdateComponent

public SendFormUpdate(): void {

    let newDate: moment.Moment = moment.utc(this.formG.value.date).local();
    this.formG.value.date = newDate.format("YYYY-MM-DD");
    const equipment: Equipments = this.formG.value;

    this.EquipmentService.PutEquipment(equipment).subscribe(result => {

      alert("Equipment was updated with success");
      this.formG.reset();
      this.dialogRef.close();
    })
}

根据DbContext.Update(Object) method

如果实体具有主键,则对于具有生成键的实体类型 值设置,那么它将在修改状态下被跟踪。

如果 未设置主键值,则将在已添加中进行跟踪 状态。这有助于确保插入新实体,而现有 实体将被更新。

一个实体被认为有它的主要 如果主键属性设置为其他任何值,则设置键值 比属性类型的 CLR 默认值。

因此,将创建新的Equipment 记录,而不是更新现有记录。


解决方案

确保您需要为equipment 分配具有值的id(主键)以解决上述问题。

DialogFormUpdateComponent

public SendFormUpdate(): void {
    ...
    
    const equipment: Equipments = this.formG.value;
    equipment.id = this.id;

    ...
}

【讨论】:

  • 哇,成功了!!谢谢你的回答和解释:)
  • 您好,不客气。请接受/支持答案,因为此答案对您有帮助。谢谢。
猜你喜欢
  • 2015-07-27
  • 2016-06-14
  • 2021-04-10
  • 1970-01-01
  • 2021-07-15
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多