Angular HttpClient – 无法将数值发布到ASP.NET CORE Web API

huangapple go评论67阅读模式
英文:

Angular HttpClient - Unable to post values to ASP.NET CORE Web API

问题

我在“form”模块中创建了一个名为“form-page”的组件:

form-page.component.html:

<form [formGroup]="form" (submit)="onSubmit()">
    <div>
        <label for="carmodel">汽车型号:</label>
        <input type="text" class="form-control" formControlName="carmodel">
        <div *ngIf="form.controls['carmodel'].touched && form.controls['carmodel'].errors">
          <div *ngIf="form.controls['carmodel'].hasError('required')" class="error">汽车型号是必填项。</div>
          <div *ngIf="form.controls['carmodel'].hasError('minlength')">汽车型号应至少为3个字符。</div>
        </div>
    </div>

    <div>
        <label for="carnum">车牌号:</label>
        <input type="text" class="form-control" formControlName="carnum">
        <div *ngIf="form.controls['carnum'].touched && form.controls['carnum'].errors">
          <div *ngIf="form.controls['carnum'].hasError('required')" class="error">车牌号是必填项。</div>
        </div>
      </div>

    <div>
        <label for="contactNumber">联系电话:</label>
        <input type="text" class="form-control" formControlName="contactNumber">
        <div *ngIf="form.controls['contactNumber'].touched && form.controls['contactNumber'].errors">
          <div *ngIf="form.controls['contactNumber'].hasError('required')" class="error">联系电话是必填项。</div>
        </div>
    </div>
  
    <div>
      <label>服务类型:</label>
      <div>
        <label><input type="radio" name="option" value="水洗" formControlName="option"> 水洗 </label>
      </div>
      <div>
        <label><input type="radio" name="option" value="全套服务" formControlName="option"> 全套服务 </label>
      </div>
      <div *ngIf="form.controls['option'].touched && form.controls['option'].invalid">
        <div class="error">请选择一个选项</div>
      </div>
    </div>
    <div>
      <label>附加服务:</label>
      <div>
        <label><input type="checkbox" value="首次服务享受10%折扣" formControlName="checkbox"> 首次服务享受10%折扣</label>
      </div>
      <div>
        <label><input type="checkbox" value="水洗享受10%折扣" formControlName="checkbox"> 水洗享受10%折扣</label>
      </div>
      <div>
        <label><input type="checkbox" value="免费空调检查" formControlName="checkbox"> 免费空调检查</label>
      </div>
      <div *ngIf="form.controls['checkbox'].touched && form.controls['checkbox'].invalid">
        <div class="error">请至少选择一个附加服务</div>
      </div>
    </div>
    <div>
      <label>省份:</label>
      <select formControlName="state" (change)="onStateChange()">
        <option *ngFor="let state of states" [value]="state">{{state}}</option>
      </select>
      <div *ngIf="form.controls['state'].touched && form.controls['state'].invalid">
        <div class="error">请选择一个省份</div>
      </div>
    </div>
 
    <div>
        <label>城市:</label>
        <select formControlName="city">
            <option *ngFor="let city of cities[form.controls['state'].value]" [value]="city">{{city}}</option>
        </select>
        <div *ngIf="form.controls[

<details>
<summary>英文:</summary>

I&#39;ve created a component &quot;form-page&quot; in the &quot;form&quot; module:

form-page.component.html:

```HTML
&lt;form [formGroup]=&quot;form&quot; (submit)=&quot;onSubmit()&quot;&gt;
    &lt;div&gt;
        &lt;label for=&quot;carmodel&quot;&gt;Car Model:&lt;/label&gt;
        &lt;input type=&quot;text&quot; class=&quot;form-control&quot; formControlName=&quot;carmodel&quot;&gt;
        &lt;div *ngIf=&quot;form.controls[&#39;carmodel&#39;].touched &amp;&amp; form.controls[&#39;carmodel&#39;].errors&quot;&gt;
          &lt;div *ngIf=&quot;form.controls[&#39;carmodel&#39;].hasError(&#39;required&#39;)&quot; class=&quot;error&quot;&gt;Carmodel is required.&lt;/div&gt;
          &lt;div *ngIf=&quot;form.controls[&#39;carmodel&#39;].hasError(&#39;minlength&#39;)&quot;&gt;Carmodel should be minimum 3 characters.&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div&gt;
        &lt;label for=&quot;carnum&quot;&gt;Car Number:&lt;/label&gt;
        &lt;input type=&quot;text&quot; class=&quot;form-control&quot; formControlName=&quot;carnum&quot;&gt;
        &lt;div *ngIf=&quot;form.controls[&#39;carnum&#39;].touched &amp;&amp; form.controls[&#39;carnum&#39;].errors&quot;&gt;
          &lt;div *ngIf=&quot;form.controls[&#39;carnum&#39;].hasError(&#39;required&#39;)&quot; class=&quot;error&quot;&gt;carnum is required.&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;



    &lt;div&gt;
        &lt;label for=&quot;contactNumber&quot;&gt;Contact Number:&lt;/label&gt;
        &lt;input type=&quot;text&quot; class=&quot;form-control&quot; formControlName=&quot;contactNumber&quot;&gt;
        &lt;div *ngIf=&quot;form.controls[&#39;contactNumber&#39;].touched &amp;&amp; form.controls[&#39;contactNumber&#39;].errors&quot;&gt;
          &lt;div *ngIf=&quot;form.controls[&#39;contactNumber&#39;].hasError(&#39;required&#39;)&quot; class=&quot;error&quot;&gt;Contact number is required.&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
  
    &lt;div&gt;
      &lt;label&gt;Type of Service:&lt;/label&gt;
      &lt;div&gt;
        &lt;label&gt;&lt;input type=&quot;radio&quot; name=&quot;option&quot; value=&quot;Waterwash&quot; formControlName=&quot;option&quot;&gt; Waterwash &lt;/label&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;label&gt;&lt;input type=&quot;radio&quot; name=&quot;option&quot; value=&quot;Fullservice&quot; formControlName=&quot;option&quot;&gt; Fullservice &lt;/label&gt;
      &lt;/div&gt;
      &lt;div *ngIf=&quot;form.controls[&#39;option&#39;].touched &amp;&amp; form.controls[&#39;option&#39;].invalid&quot;&gt;
        &lt;div class=&quot;error&quot;&gt;Please select an option&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label&gt;Addons:&lt;/label&gt;
      &lt;div&gt;
        &lt;label&gt;&lt;input type=&quot;checkbox&quot; value=&quot;10%off First service visit&quot; formControlName=&quot;checkbox&quot;&gt; 10%off First service visit&lt;/label&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;label&gt;&lt;input type=&quot;checkbox&quot; value=&quot;10%off Waterwash&quot; formControlName=&quot;checkbox&quot;&gt; 10%off Waterwash&lt;/label&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;label&gt;&lt;input type=&quot;checkbox&quot; value=&quot;Free AC Inspection&quot; formControlName=&quot;checkbox&quot;&gt; Free AC Inspection&lt;/label&gt;
      &lt;/div&gt;
      &lt;div *ngIf=&quot;form.controls[&#39;checkbox&#39;].touched &amp;&amp; form.controls[&#39;checkbox&#39;].invalid&quot;&gt;
        &lt;div class=&quot;error&quot;&gt;Please select at least one Addon&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div&gt;
      &lt;label&gt;State:&lt;/label&gt;
      &lt;select formControlName=&quot;state&quot; (change)=&quot;onStateChange()&quot;&gt;
        &lt;option *ngFor=&quot;let state of states&quot; [value]=&quot;state&quot;&gt;{{state}}&lt;/option&gt;
      &lt;/select&gt;
      &lt;div *ngIf=&quot;form.controls[&#39;state&#39;].touched &amp;&amp; form.controls[&#39;state&#39;].invalid&quot;&gt;
        &lt;div class=&quot;error&quot;&gt;Please select a state&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
 
    &lt;div&gt;
        &lt;label&gt;City:&lt;/label&gt;
        &lt;select formControlName=&quot;city&quot;&gt;
            &lt;option *ngFor=&quot;let city of cities[form.controls[&#39;state&#39;].value]&quot; [value]=&quot;city&quot;&gt;{{city}}&lt;/option&gt;
        &lt;/select&gt;
        &lt;div *ngIf=&quot;form.controls[&#39;city&#39;].touched &amp;&amp; form.controls[&#39;city&#39;].invalid&quot;&gt;
            &lt;div class=&quot;error&quot;&gt;Please select a city&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&gt;Submit&lt;/button&gt;
    &lt;button type=&quot;button&quot; (click)=&quot;Reset()&quot;&gt;Reset&lt;/button&gt;
    &lt;button (click)=&quot;goBack()&quot;&gt;back&lt;/button&gt;


    

&lt;/form&gt;

form-page.component.ts:

import { Component } from &#39;@angular/core&#39;;
import { Location } from &#39;@angular/common&#39;;
//
import { FormGroup, FormBuilder, Validators } from &#39;@angular/forms&#39;;
//
import { CarServiceService } from &#39;src/app/services/car-service.service&#39;;
@Component({
selector: &#39;app-form-page&#39;,
templateUrl: &#39;./form-page.component.html&#39;,
styleUrls: [&#39;./form-page.component.css&#39;]
})
export class FormPageComponent {
form: FormGroup;
states: string[] = [&#39;Tamilnadu&#39;, &#39;Kerala&#39;, &#39;Karnataka&#39;,&#39;Maharastra&#39;];
cities: {[key: string]: string[]} = {
&#39;Tamilnadu&#39;: [&#39;Chennai&#39;, &#39;Coimbatore&#39;,&#39;Madurai&#39;],
&#39;Kerala&#39;: [&#39;Trivandrum&#39;,&#39;Kochi&#39;,&#39;Kollam&#39;],
&#39;Karnataka&#39;: [&#39;Bangalore&#39;, &#39;Mysore&#39;],
&#39;Maharastra&#39;: [&#39;Mumbai&#39;, &#39;Pune&#39;]
};
constructor(private fb: FormBuilder,private location : Location,private carServiceService :CarServiceService) {
this.form = this.fb.group({
carmodel :[&#39;&#39;, [Validators.required, Validators.minLength(3)]],
carnum :[&#39;&#39;, [Validators.required]],
contactNumber: [&#39;&#39;, [Validators.required, Validators.pattern(/^\d{10}$/)]],
option: [&#39;&#39;, Validators.required],
checkbox: [&#39;&#39;, Validators.required],
state: [&#39;&#39;, Validators.required],
city: [&#39;&#39;, Validators.required]
});
}
goBack():void{
this.location.back();
}
onSubmit() {
if (this.form.valid) {
this.carServiceService.addCar(this.form.value).subscribe(response =&gt;{
console.log(response);
});
} else {
// Form is invalid, display error messages
this.form.markAllAsTouched();
}
}
Reset(){
this.form.reset();
}
onStateChange() {
const state = this.form.controls[&#39;state&#39;].value;
this.form.controls[&#39;city&#39;].setValue(&#39;&#39;);
if (state) {
this.form.controls[&#39;city&#39;].enable();
} else {
this.form.controls[&#39;city&#39;].disable();
}
}
//
}

Created a service named "car-service" to POST:

car-service.service.ts:

import { Injectable } from &#39;@angular/core&#39;;
import { HttpClient } from &#39;@angular/common/http&#39;;
import { Observable } from &#39;rxjs&#39;;

@Injectable({
  providedIn: &#39;root&#39;
})
export class CarServiceService {

  constructor(private http: HttpClient) { }

  addCar(formData : any): Observable&lt;any&gt;{
    return this.http.post&lt;any&gt;(&#39;https://localhost:7095/api/Forms/submit-form&#39;,formData);
  }
}

I'm trying to post the form values to the API. When I click on submit I get an error 400.

POST https://localhost:7095/api/Forms/submit-form 400

Error:

ERROR HttpErrorResponse&#160;{headers: HttpHeaders, status: 400, statusText: &#39;OK&#39;, url: &#39;https://localhost:7095/api/Forms/submit-form&#39;, ok: false,&#160;…}error: {type: &#39;https://tools.ietf.org/html/rfc7231#section-6.5.1&#39;, title: &#39;One or more validation errors occurred.&#39;, status: 400, traceId: &#39;00-88c37085e17ce434f174cf65d020c28e-1bd09d34125cb2dc-00&#39;, errors: {…}}headers: HttpHeaders&#160;{normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}message: &quot;Http failure response for https://localhost:7095/api/Forms/submit-form: 400 OK&quot;name: &quot;HttpErrorResponse&quot;ok: falsestatus: 400statusText: &quot;OK&quot;url: &quot;https://localhost:7095/api/Forms/submit-form&quot;[[Prototype]]: 

In asp.net-core web API:

FormData.cs:

namespace AngularApi.Model
{
public class FormData
{
public string Carmodel { get; set; }
public string Carnum { get; set; }
public string ContactNumber { get; set; }
public string Option { get; set; }
public List&lt;string&gt; Checkbox { get; set; }
public string State { get; set; }
public string City { get; set; }
}
}

and here is my FormController in API :

private static List&lt;FormData&gt; formsDataList = new List&lt;FormData&gt;();
[HttpPost(&quot;submit-form&quot;)]
public IActionResult SubmitForm([FromBody] FormData formData)
{
// process the form data
string carmodel = formData.Carmodel;
string carnum = formData.Carnum;
string contactNumber = formData.ContactNumber;
string option = formData.Option;
List&lt;string&gt; checkbox = formData.Checkbox;
string state = formData.State;
string city = formData.City;
// validate the form data
//           if (string.IsNullOrWhiteSpace(carmodel) || string.IsNullOrWhiteSpace(carnum) || string.IsNullOrWhiteSpace(contactNumber) || string.IsNullOrWhiteSpace(option) || checkbox == null || checkbox.Count == 0 || string.IsNullOrWhiteSpace(state) || string.IsNullOrWhiteSpace(city))
//          {
//              return BadRequest(new { Message = &quot; Enter the required fields.&quot; });
//         }
formsDataList.Add(formData);
//            return Ok(new { Message = &quot;Form submitted successfully.&quot; });
return Ok(formData);
}

The inputs are not even hitting API. So I suspect the problem is with HTTPClient and with the checkbox.I guess The problem lies with the checkbox. Because if I remove the checkbox field entirely from both HTML form and API, it works perfectly and I'm able to post values to API.

Can someone tell me How to resolve this.

答案1

得分: 1

Solution 1: Post request data as JSON body.

使用 [FromBody] 属性,而不是 [FromForm] 属性。

[HttpPost("submit-form")]
public IActionResult SubmitForm([FromBody] FormData formData)

Solution 2: Send the request data with the Content-Type: application/x-www-form-urlencoded.

将请求数据发送为 application/x-www-form-urlencoded 类型。

export class CarServiceService {

  addCar(formData: any): Observable<any> {
    let body = new URLSearchParams();
    body.set('carmodel', formData.carmodel);
    body.set('carnum', formData.carnum);
    body.set('contactNumber', formData.contactNumber);
    body set('option', formData.option);

    for (let c of formData.checkbox)
      body.set('selectedCheckboxes[]', c);

    body.set('selectstate', formData.state);
    body.set('selectcity', formData.city);

    return this.http.post<any>('https://localhost:7095/api/Forms/submit-form', body);
  }
}
英文:

With the [FromForm] attribute, your API expects to receive the form data with the Content-Type: application/x-www-form-urlencoded. But on the Angular side, you are posting the request body with the Content-Type: application/json.

Thus, the API cannot process the request and return the response with a 400 status code.


Solution 1: Post request data as JSON body.

Use [FromBody] attribute instead of [FromForm] attribute.

[HttpPost(&quot;submit-form&quot;)]
public IActionResult SubmitForm([FromBody] FormData formData)

Solution 2: Send the request data with the Content-Type: application/x-www-form-urlencoded.

export class CarServiceService {

  addCar(formData : any): Observable&lt;any&gt; {
    let body = new URLSearchParams();
    body.set(&#39;carmodel&#39;, formData.carmodel);
    body.set(&#39;carnum&#39;, formData.carnum);
    body.set(&#39;contactNumber&#39;, formData.contactNumber);
    body.set(&#39;option&#39;, formData.option);

    for (let c of formData.checkbox)
      body.set(&#39;selectedCheckboxes[]&#39;, c);

    body.set(&#39;selectstate&#39;, formData.state);
    body.set(&#39;selectcity&#39;, formData.city);

    return this.http.post&lt;any&gt;(&#39;https://localhost:7095/api/Forms/submit-form&#39;, body);
  }
}

And note that a 400 Bad Request status could happen when the API is unable to deserialize the request body and map to the parameter due to the unmatched field/property type. For example, in Angular, you are sending the checkbox as string in Angular, but formData.SelectedCheckbox is expecting a value with List&lt;string&gt; type.

huangapple
  • 本文由 发表于 2023年3月31日 22:06:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75899466.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定