Why isn't my C# endpoint understanding my Angular Reactive form data?

Blue

Apologies - Angular and typescript are still relatively Greek to me. Long story short, when I post my form to a C#/.NET 3.1 endpoint, all of the key value pairs from my form are smooshed together into one big key with no corresponding value.

I've put together a form in an Angular component, like

export class DialogFileUpload {
    uploadForm = this.fb.group({
       isFoo:[''],
       hasHeaders:['', [Validators.required]],
       distributor:[''],
       file:['']
    });

    date = new FormControl(moment());
    
    distributors: IDistributor[] = [];


    get aliases() {
        return this.uploadForm.get('aliases') as FormArray;
    }
    constructor(
        public dialogRef: MatDialogRef<DialogFileUpload>,
        private fb: FormBuilder,
        private distributorService: DistributorService,
        private uploadService: UploadService) {}

    ngOnInit() {
        this.distributorService.getDistributors()
            .subscribe(distributors => {
                this.distributors = distributors;
            })
...

My corresponding HTML looks like

<form [formGroup]="uploadForm" (ngSubmit)="onSubmit()">
  <mat-form-field>
    <input matInput formControlName="effectiveMonth" [matDatepicker]="picker" [min]="sixMonthsAgo" [max]="today" placeholder="Effective Month">
    <mat-datepicker-toggle  matSuffix [for]="picker"></mat-datepicker-toggle>
    <mat-datepicker #picker 
                    startView="multi-year"
                    (yearSelected) = "chosenYearHandler($event)"
                    (monthSelected)= "closeDatePicker($event, picker)">
    </mat-datepicker>
  </mat-form-field>

  <mat-form-field appearance="fill" class="distributor-select">
    <mat-label>Distributor</mat-label>
    <mat-select formControlName="distributor">
      <mat-option value="-1">--</mat-option>
      <mat-option *ngFor="let distributor of distributors" [value]="distributor.id">
        {{distributor.name}}
      </mat-option>
    </mat-select>
  </mat-form-field>
  <input type="file" formControlName="file" (change)="appendFile($event.target.files)">

  <mat-radio-group 
    formControlName="isFoo">
    <mat-radio-button value="true">foo</mat-radio-button>
    <mat-radio-button value="false">Non-foo</mat-radio-button>
  </mat-radio-group>
  <mat-radio-group *ngIf="uploadForm.value.isFoo == 'false'"
    formControlName="hasHeaders">
    <mat-radio-button value="true">Has Headers</mat-radio-button>
    <mat-radio-button value="false">Headerless</mat-radio-button>
  </mat-radio-group>

  <div mat-dialog-actions>
    <button mat-button (click)="onNoClick()">Cancel</button>
    <button mat-raised-button color="primary" cdkFocusInitial>Ok</button>
  </div>
</form>

<br>{{uploadForm.value | json}}

As an aside, the uploadForm.value appears to be formatted correctly Once the form is completed, there's this call:

   onSubmit(): void {
        console.log(this.uploadForm.value);
        this.uploadService.postFileToServer(this.uploadForm.value)
            .subscribe({
                next: () =>{},
                error: () => {},
                complete: () =>{
                    this.dialogRef.close();
                    window.location.reload();

                }
            })
    }

Which calls this:

postFileToServer(data: FormData) {
    let url = this.baseUrl + this.fileUploadUrl;
    return this.http.post(url, data, {headers : { "Content-Type" : "Application/x-www-form-urlencoded"}});

}

Should this be application/x-www-form-urlencoded? Multipart/form-data? I get errors in my backend if I use the latter. Anyway, the corresponding endpoint looks like this

    [HttpPost]
    [DisableRequestSizeLimit]

    public IActionResult UploadEdiFile() {

        var foo = Request.Form;
        
        Console.WriteLine(foo["distributor"]);
        bool isFoo = Request.Form["isFoo"] == "true" ? true : false;

And it turns up that 'isFoo' returns null. In looking at the request object, I see only one key and no value, it's like it's combined all my key values into one lump.

{[{"isFoo":"true","hasHeaders":"true","distributor":"5","file":"","effectiveMonth":"2021-06-21T22:54:18.038Z"}, {}]}

The uploadForm.value || json displayed in browser, however, looks like:

{ "isFoo": "true", "hasHeaders": "true", "distributor": "5", "file": "", "effectiveMonth": "2021-06-21T22:51:39.688Z" }

Where'd I mess up?

Blue

Per the comments on the question, I think this is good to go - though it feels more like a workaround than a happy path.

When adding a file to the form, the following is called:

appendFile(uploadFile: File) : void {
    this.uploadForm.controls['file'].setValue(uploadFile, uploadFile ? uploadFile.name : '');
}

The new version of my onSubmit method, however, looks like this:

onSubmit(): void {
    const formData = new FormData();
    formData.append('file', this.uploadForm.get('file').value[0]);
    formData.append('isFoo', this.uploadForm.get('isFoo').value);
    formData.append('hasHeasders', this.uploadForm.get('hasHeaders').value);
    formData.append('effectiveMonth', this.uploadForm.get('effectiveMonth').value);
    formData.append('distributor', this.uploadForm.get('distributor').value);
    this.uploadService.postFileToServer(formData)
        .subscribe({
            next: () =>{},
            error: () => {},
            complete: () =>{
                this.dialogRef.close();
                window.location.reload();

            }
        })
}

It now creates a new instance of FormData, and appends each element from the FormGroup, which is then posted. The post method no longer needs some sort of special content-type callout, and indeed the urlencodedform nor multipart/form-data did me any favors.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why my Reactive form validation failed in Angular

Why isn't my <h:form> visible?

Why isn't my React Form sending?

Why isn't my form working?

Why isn't my form submitting

Why isn't my PHP form working?

Meteor: Why my template helper isn't reactive?

Why isn't my svelte {#each} block reactive?

Why don't getters for form errors work in my Angular Reactive Form component template, but a direct reference does?

Why isn't data rendering on my template from my Angular scope?

Why isn't my data plotting to my pcolor plot?

Why isn't my code posting data from my database?

Why isn't my data being retrieved on my NodeJS Backend?

Why isn't my user inserted in my mongoDB? spring webFlux reactive REST

Why isn't my if statement function populating my variable (C)?

Why isn't my form saving but working with the API only?

Why isn't my Create Form working, or even responding?

Why isn't my form passing the id to the controller?

Why isn't my async Angular Jasmine unit test working?

Why isn't Angular calling registerOnChange in my implementation of ControlValueAccessor?

Why isn't my Angular Sequence Method working?

Why isn't my angular directive pulling in this attribute?

Why isn't my Angular 4 ChartJS component rendering?

Why isn´t angular syncing my var bound with ngModel?

Angular why my boolean in service isn't updating in html?

Why isn't my JavaScript saving data locally?

Why isn't my data writing to the excel destination? SSIS

Why isn't my data persisting after using SavedStateHandle?

Why isn't my AngularJS post receiving data from the server?