代码之家  ›  专栏  ›  技术社区  ›  EggBender

Angular HttpClient在Router.navigate()之后停止工作。接收400(错误请求)

  •  0
  • EggBender  · 技术社区  · 6 年前

    由于某种原因,在我使用路由器导航之后,HttpClient请求开始接收400(错误请求)。在导航之前,HttpClient使用完全相同的http调用方法工作得非常好。以下是导航:

    let navigationExtras: NavigationExtras = {
      queryParams: {
        "certificate": JSON.stringify(this.selection.selected[0])
      }
    };
    this.router.navigate(["create"],  navigationExtras);
    

    enter image description here

    我知道这不是ASP.NET核心控制器中的CORS问题,因为在导航之前不会发生错误请求,并且我确实允许服务器端的CORS。

      @Component({
      selector: 'app-history',
      templateUrl: './history.component.html',
      styleUrls: ['./history.component.css']
    })
    export class HistoryComponent implements OnInit {
    
      certificates: CertificateModel[] = [];
      dataSource : MatTableDataSource<CertificateModel> = new MatTableDataSource(this.certificates);
      displayedColumns: string[] = ['name', 
                                    'customer', 
                                    'customerOrderNo', 
                                    'certificateNo',
                                    'orderACKNNo',
                                    'date',
                                    'select'];
      @ViewChild(MatSort) sort: MatSort
      @ViewChild("paginator") paginator: MatPaginator;
      searchTextfield: string;
      searchOptions: string[] = ["Name", "Customer", "Cust. Ord. No.", "Order ACKN No.", "Date"];
      selectedSearchOption: string = "Name";
      selection = new SelectionModel<CertificateModel>(true, []);
      isLoading:  boolean;
    
      constructor(private certHttpService: CertificateHttpService,
        public errorDialog: MatDialog,
        private router: Router
        ) { }
    
      ngOnInit() {
        this.configureDataSource();
        this.loadCertificates();
      }
    
      loadCertificates() {
        this.isLoading = true;
        this.certHttpService.getAllPro().then((res => {
          this.certificates = res; 
          this.dataSource.data = this.certificates;
          this.isLoading = false;
        }).bind(this))
        .catch((error => {
          this.isLoading = false;
          this.openErrorDialog("Error", error.name + ": " + error.message);
        }).bind(this));
      }
    
      openErrorDialog(title: string, text: string) {
        var data = {
          "title": title,
          "text": text
        };
    
        const dialogRef = this.errorDialog.open(ErrorDialogComponent, {
          width: '30vw',
          height: 'auto',
          disableClose: true,
          data: data
        });
    
        dialogRef.afterClosed().subscribe(result => {
          console.log('The dialog was closed');
        });
      }
    
      editClicked() {
        let navigationExtras: NavigationExtras = {
          queryParams: {
            "certificate": JSON.stringify(this.selection.selected[0])
          }
        };
        this.router.navigate(["create"],  navigationExtras);
      }
    
      deleteClicked() {
        this.certHttpService.deletePro(this.selection.selected).then((res => {
          this.selection.selected.forEach(e0 => {
            var index = this.certificates.findIndex(e1 => {
              return e0.guid == e1.guid;
            });
            this.certificates.splice(index, 1);
          });
          this.dataSource = new MatTableDataSource<CertificateModel>(this.certificates);
          this.configureDataSource();
          this.selection = new SelectionModel<CertificateModel>(true, []);
        }).bind(this));
      }
    
      searchFieldOnChange() {
        console.log("searchfield on change!");
        
      }
      
      applyFilter(filterValue: string) {
        filterValue = filterValue.toLowerCase();
        this.dataSource.filter = filterValue;
      }
    
      isAllSelected() : boolean {
        const numSelected = this.selection.selected.length;
        const numRows = this.dataSource.data.length;
        return numSelected == numRows;
      }
    
      masterToggle() {
        this.isAllSelected() ?
          this.selection.clear() :
          this.dataSource.data.forEach(row => this.selection.select(row));
      }
    
      configureDataSource () {
        this.dataSource.sortingDataAccessor = (data: any, sortHeaderId: string): string => {
          if (typeof data[sortHeaderId] === 'string')
            return data[sortHeaderId].toLocaleLowerCase();
          return data[sortHeaderId];
        };
        this.dataSource.sort = this.sort;
        this.dataSource.paginator = this.paginator;
        this.dataSource.filterPredicate = 
          ((data: CertificateModel, filter: string) => {
            if(this.selectedSearchOption == this.searchOptions[0] && data.name != null)
              return data.name.toLowerCase().indexOf(filter) != -1;
            else if(this.selectedSearchOption == this.searchOptions[1] && data.customer != null)
              return data.customer.toLowerCase().indexOf(filter) != -1;
            else if(this.selectedSearchOption == this.searchOptions[2] && data.customerOrderNo != null)
              return data.customerOrderNo.toLowerCase().indexOf(filter) != -1;
            else if(this.selectedSearchOption == this.searchOptions[3] && data.customerArtNo != null)
              return data.customerArtNo.toLowerCase().indexOf(filter) != -1;
            else if(this.selectedSearchOption == this.searchOptions[4] && data.date != null)
              return data.date.toLowerCase().indexOf(filter) != -1;
          });
      }
    
      refreshClicked() {
        this.loadCertificates();
      }
    
    }
    
      @Component({
      selector: 'app-create-cert',
      templateUrl: './create-cert.component.html',
      styleUrls: ['./create-cert.component.css'],
      encapsulation: ViewEncapsulation.None
    })
    export class CreateCertComponent implements OnInit {
    
      resultRowWrappers: ResultRowWrapper[];
      customerTextfield: string;
      customerOrderNoTextfield: string;
      customerArtNoTextfield: string;
      specificationTextfield: string;
      certificateNoTextfield: string;
      dateTextfield: string;
      deliveredQuantityTextfield: string;
      orderACKNNoTextfield: string;
      batchNumberTextfield: string;
      propertyTextfield: string;
      unitTextfield: string;
      testResultTextfield: string;
      signaturTextfield: string;
      newCertName: string;
      editedCertificate: CertificateModel
      isEditing: boolean;
      disableDeleteButton: boolean;
      titleRow0Textfield: string;
      titleRow1Textfield: string;
      titleRow2Textfield: string;
      titleRow3Textfield: string;
      selectedLogoAddressCard : LogoAddressCardModel;
    
      constructor(
        public previewDialog: MatDialog,
        public errorDialog: MatDialog,
        public nameDialog: MatDialog,
        public logoDIalog: MatDialog,
        private certHttpService: CertificateHttpService,
        public snackBar: MatSnackBar,
        private route: ActivatedRoute) { }
    
      ngOnInit() {
        console.log("On init called in create cert component!");
        
        this.selectedLogoAddressCard = {
          logo: "",
          addressRow0: "Address row 0",
          addressRow1: "Address row 1",
          addressRow2: "Address row 2",
          guid: Guid.create().toString()
        };
        this.disableDeleteButton = true;
        this.isEditing = false;
        this.resultRowWrappers = [];
        this.propertyTextfield = "";
        this.unitTextfield = "";
        this.testResultTextfield = "";
        this.route.queryParams.subscribe(params => {
          try {
            var certificate = JSON.parse(params["certificate"]);
            this.editedCertificate = certificate;
            this.fillInputFields(certificate);
            this.selectedLogoAddressCard = certificate.logoAddressCard;
          } catch{
            console.log("CATCH: No cert in params.");
            return;
          }
        });
      }
    
      openPreviewDialog(): void {
        var newCertificate = this.createCertificateFromInputs(Guid.create().toString());
    
        const dialogRef = this.previewDialog.open(PreviewDialogComponent, {
          width: '30vw',
          height: '99vh',
          disableClose: false,
          panelClass: "preview-dialog-container",
          data: newCertificate
        });
    
        dialogRef.updatePosition({ top: '2px' });
        dialogRef.afterClosed().subscribe(result => {
          this.snackBar.dismiss();
        });
      }
    
      openLogosDialog(): void {
        const dialogRef = this.logoDIalog.open(LogosDialogComponent, {
          width: '60vw',
          height: '95vh',
          disableClose: true,
          panelClass: "logo-dialog-container"
        });
        dialogRef.updatePosition({top: "10px"});
        var _this = this;
        dialogRef.componentInstance.cardSelectedEvent.subscribe((res: AppCard) => {
          _this.selectedLogoAddressCard = res.cardModel;
        });
      }
    
      openErrorDialog(title: string, text: string) {
        var data = {
          "title": title,
          "text": text
        };
    
        const dialogRef = this.errorDialog.open(ErrorDialogComponent, {
          width: '30vw',
          height: 'auto',
          disableClose: true,
          data: data
        });
    
        dialogRef.afterClosed().subscribe(result => {
          console.log('The dialog was closed');
        });
      }
    
      saveResultRowClicked() {
        var newResultRow: ResultRow = {
          property: this.propertyTextfield,
          unit: this.unitTextfield,
          testResult: this.testResultTextfield
        };
        var newResultRowWrapper: ResultRowWrapper = {
          resultRow: newResultRow,
          isChecked: false
        }
        this.resultRowWrappers.push(newResultRowWrapper);
        this.propertyTextfield = "";
        this.unitTextfield = "";
        this.testResultTextfield = "";
      }
    
      deleteResultRowClicked() {
        for (var i = 0; i < this.resultRowWrappers.length; i++)
          if (this.resultRowWrappers[i].isChecked) {
            this.resultRowWrappers.splice(i, 1);
            i--;
          }
      }
    
      saveClicked() {
        var _this = this;
        const dialogRef = this.nameDialog.open(CertNameDialogComponent, {
          width: '40vw',
          height: '37.5vh',
          disableClose: true,
          data: {
            "currentName": ""
          }
        }).componentInstance.saveClickedEvent.subscribe(res => {
          _this.newCertName = res;
          _this.saveCertificate();
        });
      }
    
      saveEditClicked() {
        var _this = this;
        const dialogRef = this.nameDialog.open(CertNameDialogComponent, {
          width: '40vw',
          height: '37.5vh',
          disableClose: true,
          data: {
            "currentName": this.editedCertificate.name
          }
        }).componentInstance.saveClickedEvent.subscribe(res => {
          _this.newCertName = res;
          _this.overwriteCertificate();
        });
      }
    
      saveCertificate() {
        var newCertificate = this.createCertificateFromInputs(Guid.create().toString());
    
        this.certHttpService.insertPro(newCertificate)
          .then((res => {
            this.nameDialog.closeAll();
            this.openSnackBar("Saved certificate " + "\"" + newCertificate.name + "\"", "Close", "right", "bottom", 1*3000);
          }).bind(this))
          .catch(((error) => {
            this.nameDialog.closeAll();
            this.openErrorDialog("Error", error.name + ": " + error.message);
          }).bind(this));
      }
    
      overwriteCertificate() {
        var newCertificate = this.createCertificateFromInputs(this.editedCertificate.guid);
    
        this.certHttpService.overwritePro(newCertificate)
          .then((res => {
            this.nameDialog.closeAll();
            this.openSnackBar("Saved certificate " + "\"" + newCertificate.name + "\"", "Close", "right", "bottom", 1*3000);
          }).bind(this))
          .catch(((error) => {
            this.nameDialog.closeAll();
            this.openErrorDialog("Error", error.name + ": " + error.message);
          }).bind(this));
      }
    
      createCertificateFromInputs(guid: string): CertificateModel {
        var resultRows: ResultRow[] = [];
        this.resultRowWrappers.forEach(e => {
          resultRows.push(e.resultRow);
        });
    
        var certificate: CertificateModel = {
          batchNumber: this.batchNumberTextfield,
          certificateNo: this.certificateNoTextfield,
          customer: this.customerTextfield,
          customerArtNo: this.customerArtNoTextfield,
          customerOrderNo: this.customerOrderNoTextfield,
          date: this.dateTextfield,
          deliveredQuantity: this.deliveredQuantityTextfield,
          orderACKNNo: this.orderACKNNoTextfield,
          specification: this.specificationTextfield,
          resultRows: resultRows,
          name: this.newCertName,
          signature: this.signaturTextfield,
          guid: guid,
          titleRow0: this.titleRow0Textfield,
          titleRow1: this.titleRow1Textfield,
          titleRow2: this.titleRow2Textfield,
          titleRow3: this.titleRow3Textfield,
          logoAddressCard: this.selectedLogoAddressCard
        };
    
        return certificate;
      }
    
      previewClicked() {
        this.openPreviewDialog();
        this.openSnackBar("Click outside the preview dialog to close.", "Close", "right", "bottom", 24 * 60 * 60 * 1000);
      }
    
      fillInputFields(certificate: CertificateModel) {
        this.isEditing = true;
        // this.openSnackBar("Editing certificate " + "\"" + certificate.name + "\"", "Close", "right", "bottom", 5 * 1000);
        this.resultRowWrappers = [];
        if (certificate.resultRows != null)
          if (certificate.resultRows.length > 0)
            certificate.resultRows.forEach(e => {
              var resultRow: ResultRowWrapper = {
                resultRow: e,
                isChecked: false
              };
              this.resultRowWrappers.push(resultRow);
            });
        this.customerArtNoTextfield = certificate.customerArtNo;
        this.customerOrderNoTextfield = certificate.customerOrderNo;
        this.customerTextfield = certificate.customer;
        this.batchNumberTextfield = certificate.batchNumber;
        this.certificateNoTextfield = certificate.certificateNo;
        this.deliveredQuantityTextfield = certificate.deliveredQuantity;
        this.dateTextfield = certificate.date;
        this.orderACKNNoTextfield = certificate.orderACKNNo;
        this.signaturTextfield = certificate.signature;
        this.specificationTextfield = certificate.specification;
        this.titleRow0Textfield = certificate.titleRow0;
        this.titleRow1Textfield = certificate.titleRow1;
        this.titleRow2Textfield = certificate.titleRow2;
        this.titleRow3Textfield = certificate.titleRow3;
        this.selectedLogoAddressCard = certificate.logoAddressCard;
      }
    
      openSnackBar(message: string, action: string, hPosition: string, vPosition: string, duration: number) {
        this.snackBar.open(message, action, {
          duration: duration,
          horizontalPosition: hPosition as MatSnackBarHorizontalPosition,
          verticalPosition: vPosition as MatSnackBarVerticalPosition
        });
      }
    
      checkBoxClickedEvent() {
        var areAnyChecked = false;
        this.resultRowWrappers.forEach(e => {
          if (e.isChecked) {
            areAnyChecked = true;
            return;
          }
        });
        this.disableDeleteButton = !areAnyChecked;
      }
    
      selectCardClicked() {
        this.openLogosDialog();
      }
    
    }
    

    导航后停止工作的已用http服务的代码:

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { LogoAddressCardModel } from 'src/data_models/LogoAddressCardModel';
    import { RequestOptions } from '@angular/http';
    
    @Injectable({
      providedIn: 'root'
    })
    export class LogoAddressCardHttpServiceService {
    
      constructor(private httpClient: HttpClient) { }
    
      getAllObs(): Observable<LogoAddressCardModel[]> {
        return this.httpClient.get<LogoAddressCardModel[]>("http://localhost:50219/api/logo_address_card/get_all");
      }
    
      async getAllPro(): Promise<LogoAddressCardModel[]> {
        var response = await this.getAllObs();
        return response.toPromise();
      }
    
      insertObs(model: LogoAddressCardModel): Observable<any> {
        console.log(model.addressRow0);
        console.log(model.addressRow1);
        console.log(model.addressRow2);
    
        return this.httpClient.post<any>("http://localhost:50219/api/logo_address_card/insert", model);
      }
    
      async insertPro(model: LogoAddressCardModel): Promise<any> {
        var response = await this.insertObs(model);
        return response.toPromise();
      }
    
      overwriteObs(model: LogoAddressCardModel): Observable<any> {
        return this.httpClient.post<any>("http://localhost:50219/api/logo_address_card/overwrite", model);
      }
    
      async overwritePro(model: LogoAddressCardModel): Promise<any> {
        var response = await this.overwriteObs(model);
        return response.toPromise();
      }
    
      deleteObs(model: LogoAddressCardModel): Observable<any> {
        return this.httpClient.post<any>("http://localhost:50219/api/logo_address_card/delete", model);
      }
    
      async deletePro(model: LogoAddressCardModel): Promise<any> {
        var response = await this.deleteObs(model);
        return response.toPromise();
      }
    
    }
    

    为什么相同的http服务和http调用方法首先工作,而不是稍后工作?我完全被搞糊涂了,想把自己的头发扯下来。

    1 回复  |  直到 3 年前
        1
  •  0
  •   EggBender    6 年前

    使用NavigationExtras的问题是,它们在发出HTTP请求时被添加到URL中。这就是导致错误请求的原因。API控制器在URL中获得了一系列它没有预料到的参数。