英文:
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've created a component "form-page" in the "form" module:
form-page.component.html:
```HTML
<form [formGroup]="form" (submit)="onSubmit()">
<div>
<label for="carmodel">Car Model:</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">Carmodel is required.</div>
<div *ngIf="form.controls['carmodel'].hasError('minlength')">Carmodel should be minimum 3 characters.</div>
</div>
</div>
<div>
<label for="carnum">Car Number:</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">carnum is required.</div>
</div>
</div>
<div>
<label for="contactNumber">Contact Number:</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">Contact number is required.</div>
</div>
</div>
<div>
<label>Type of Service:</label>
<div>
<label><input type="radio" name="option" value="Waterwash" formControlName="option"> Waterwash </label>
</div>
<div>
<label><input type="radio" name="option" value="Fullservice" formControlName="option"> Fullservice </label>
</div>
<div *ngIf="form.controls['option'].touched && form.controls['option'].invalid">
<div class="error">Please select an option</div>
</div>
</div>
<div>
<label>Addons:</label>
<div>
<label><input type="checkbox" value="10%off First service visit" formControlName="checkbox"> 10%off First service visit</label>
</div>
<div>
<label><input type="checkbox" value="10%off Waterwash" formControlName="checkbox"> 10%off Waterwash</label>
</div>
<div>
<label><input type="checkbox" value="Free AC Inspection" formControlName="checkbox"> Free AC Inspection</label>
</div>
<div *ngIf="form.controls['checkbox'].touched && form.controls['checkbox'].invalid">
<div class="error">Please select at least one Addon</div>
</div>
</div>
<div>
<label>State:</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">Please select a state</div>
</div>
</div>
<div>
<label>City:</label>
<select formControlName="city">
<option *ngFor="let city of cities[form.controls['state'].value]" [value]="city">{{city}}</option>
</select>
<div *ngIf="form.controls['city'].touched && form.controls['city'].invalid">
<div class="error">Please select a city</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" (click)="Reset()">Reset</button>
<button (click)="goBack()">back</button>
</form>
form-page.component.ts:
import { Component } from '@angular/core';
import { Location } from '@angular/common';
//
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
//
import { CarServiceService } from 'src/app/services/car-service.service';
@Component({
selector: 'app-form-page',
templateUrl: './form-page.component.html',
styleUrls: ['./form-page.component.css']
})
export class FormPageComponent {
form: FormGroup;
states: string[] = ['Tamilnadu', 'Kerala', 'Karnataka','Maharastra'];
cities: {[key: string]: string[]} = {
'Tamilnadu': ['Chennai', 'Coimbatore','Madurai'],
'Kerala': ['Trivandrum','Kochi','Kollam'],
'Karnataka': ['Bangalore', 'Mysore'],
'Maharastra': ['Mumbai', 'Pune']
};
constructor(private fb: FormBuilder,private location : Location,private carServiceService :CarServiceService) {
this.form = this.fb.group({
carmodel :['', [Validators.required, Validators.minLength(3)]],
carnum :['', [Validators.required]],
contactNumber: ['', [Validators.required, Validators.pattern(/^\d{10}$/)]],
option: ['', Validators.required],
checkbox: ['', Validators.required],
state: ['', Validators.required],
city: ['', Validators.required]
});
}
goBack():void{
this.location.back();
}
onSubmit() {
if (this.form.valid) {
this.carServiceService.addCar(this.form.value).subscribe(response =>{
console.log(response);
});
} else {
// Form is invalid, display error messages
this.form.markAllAsTouched();
}
}
Reset(){
this.form.reset();
}
onStateChange() {
const state = this.form.controls['state'].value;
this.form.controls['city'].setValue('');
if (state) {
this.form.controls['city'].enable();
} else {
this.form.controls['city'].disable();
}
}
//
}
Created a service named "car-service" to POST:
car-service.service.ts:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CarServiceService {
constructor(private http: HttpClient) { }
addCar(formData : any): Observable<any>{
return this.http.post<any>('https://localhost:7095/api/Forms/submit-form',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 {headers: HttpHeaders, status: 400, statusText: 'OK', url: 'https://localhost:7095/api/Forms/submit-form', ok: false, …}error: {type: 'https://tools.ietf.org/html/rfc7231#section-6.5.1', title: 'One or more validation errors occurred.', status: 400, traceId: '00-88c37085e17ce434f174cf65d020c28e-1bd09d34125cb2dc-00', errors: {…}}headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}message: "Http failure response for https://localhost:7095/api/Forms/submit-form: 400 OK"name: "HttpErrorResponse"ok: falsestatus: 400statusText: "OK"url: "https://localhost:7095/api/Forms/submit-form"[[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<string> Checkbox { get; set; }
public string State { get; set; }
public string City { get; set; }
}
}
and here is my FormController in API :
private static List<FormData> formsDataList = new List<FormData>();
[HttpPost("submit-form")]
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<string> 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 = " Enter the required fields." });
// }
formsDataList.Add(formData);
// return Ok(new { Message = "Form submitted successfully." });
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("submit-form")]
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<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);
}
}
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<string>
type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论