[英]Problems with getting angular 8 to post http request, Postman works fine
I'm having some problems getting angular to post my data to the API backend.我在将我的数据发布到 API 后端时遇到了一些问题。 The API works fine with Postman.
API 与 Postman 配合良好。
I have a service for the Observable and then I subscribe to it in the component.我有一个 Observable 服务,然后我在组件中订阅它。
What am I trying to do?我想做什么? I'm trying to post to my backend api/database the firstname, lastname and emaladdress from the html form.
我正在尝试将 html 表单中的名字、姓氏和 emaladdress 发布到我的后端 api/数据库。 If I use Postman it works perfectly, so I don't see that the problem is with the API part.
如果我使用 Postman,它可以完美运行,所以我看不出问题出在 API 部分。 The html has a form in which calls the OnFormSubmit() function.
html 有一个调用 OnFormSubmit() 函数的表单。 This in turn calls the createArticle(article) function in the article.component.ts, which uses the articleService.createArticle(article) function in the article.service.ts file.
这反过来调用article.component.ts 中的createArticle(article) 函数,该函数使用article.service.ts 文件中的articleService.createArticle(article) 函数。 When I run the CreateArticle(article) the data/values are passed and returned but in the backend api, they are never written.
当我运行 CreateArticle(article) 时,数据/值被传递并返回,但在后端 api 中,它们从未被写入。 If I use Postman and add the values for firstname, lastname, and emailaddress it works prefectly.
如果我使用 Postman 并添加名字、姓氏和电子邮件地址的值,它就可以完美地工作。
EmailsubControler.cs This is from the backend api, which works fine with postman EmailsubControler.cs这是来自后端api,与邮递员一起工作正常
//Post an entry to email addresses
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Post(string firstname, string lastname, string emailaddress)
{
var newemailsub = new EmailSubscriptionModel{ Firstname = firstname, Lastname = lastname, Emailaddress = emailaddress};
await _context.EmailSub.AddAsync(newemailsub);
await _context.SaveChangesAsync();
return Ok(newemailsub);
}
article.component.ts文章.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Observable, Observer } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { ArticleService } from './article.service';
import { Article } from './article';
import { map } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
@Component({
selector: 'app-article',
templateUrl: './article.component.html',
styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
constructor(private formBuilder: FormBuilder, private articleService: ArticleService, private http: HttpClient) { }
get firstname() {
return this.articleForm.get('firstname');
}
get lastname() {
return this.articleForm.get('lastname');
}
get emailaddress() {
return this.articleForm.get('emailaddress');
}
dataSaved = false;
articleForm: FormGroup;
allArticles$: Observable<Article[]>;
time = new Observable<string>((observer: Observer<string>) => {
setInterval(() => observer.next(new Date().toString()), 1000);
});
ngOnInit() {
this.articleForm = this.formBuilder.group({
firstname: ['', [ Validators.required ] ],
lastname: ['', [ Validators.required ] ],
emailaddress: ['', [ Validators.required ] ]
});
// this.loadAllArticles();
}
onFormSubmit() {
console.log('articleafterdataSaved', this.articleForm.value);
this.dataSaved = false;
let article = this.articleForm.value;
this.articleService.getAllArticles().subscribe(articles => {
this.createArticle(article);
});
this.articleForm.reset();
}
createArticle(article) {
console.log('articledataincreatearticle', article);
this.articleService.createArticle(article)
.subscribe(
Response => console.log('insubscribe-returned:', article),
this.dataSaved = true,
this.loadAllArticles()
);
}
loadAllArticles() {
this.allArticles$ = this.articleService.getAllArticles();
}
}
article.ts This is the interface article.ts这是界面
export interface Article {
id?: number;
firstname: string;
lastname: string;
emailaddress: string;
}
article.service.ts article.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { Article } from './article';
import { map } from 'rxjs/operators';
import { catchError, retry } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ArticleService {
url = "https://localhost:5001/emailsub";
constructor(private http: HttpClient) { }
/* createArticle(article: Article): Observable<Article> {
console.log('1inservicearticle', article);
let httpHeaders = new HttpHeaders()
.set('Content-Type', 'application/json');
let options = {
headers: httpHeaders
};
console.log('inservicearticle', article);
console.log('inservicearticle', this.url);
// return this.http.post<Article>(this.url, article, options);
return this.http.post<Article>(this.url, article, options);
} */
errorHand1: any;
httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
createArticle(article): Observable<Article> {
console.log('1inservicearticle', article);
console.log('inservicearticle-article', article);
console.log('inservicearticle-url', this.url);
console.log('inservicearticle-JSON', JSON.stringify(article));
// return this.http.post<Article>(this.url, article, options);
return this.http.post<Article>(this.url, JSON.stringify(article), this.httpOptions)
.pipe(
retry(1),
catchError(this.errorHand1)
);
}
postArticle(article: Article): Observable<HttpResponse<Article>> {
let httpHeaders = new HttpHeaders({
'Content-Type' : 'application/json'
});
console.log('inservice', article.firstname);
return this.http.post<Article>(this.url, article,
{
headers: httpHeaders,
observe: 'response'
}
);
}
getAllArticles(): Observable<Article[]> {
return this.http.get<Article[]>(this.url);
}
}
article.component.html文章.component.html
<h3>Create Article</h3>
<p *ngIf="dataSaved && articleForm.pristine" ngClass = "success">
Article created successfully.
</p>
<form [formGroup]="articleForm" (ngSubmit)="onFormSubmit()">
<table>
<tr>
<td>firstname: </td>
<td>
<input formControlName="firstname">
<div *ngIf="firstname.dirty && firstname.errors" class = "error">
<div *ngIf="firstname.errors.required">
firstname required.
</div>
</div>
</td>
</tr>
<tr>
<td>lastname: </td>
<td>
<input formControlName="lastname">
<div *ngIf="lastname.dirty && lastname.errors" class = "error">
<div *ngIf="lastname.errors.required">
lastname required.
</div>
</div>
</td>
</tr>
<tr>
<td>emailaddress: </td>
<td>
<input formControlName="emailaddress">
<div *ngIf="emailaddress.dirty && emailaddress.errors" class = "error">
<div *ngIf="emailaddress.errors.required">
emailaddress required.
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<button [disabled]="articleForm.invalid">Submit</button>
</td>
</tr>
</table>
</form>
<h3>Article Details</h3>
<p *ngFor="let article of allArticles$ | async">
{{article.id}} | {{article.firstname}} |
{{article.lastname}} | {{article.emailaddress}}
</p>
<div><code>observable|async</code>: Time: {{ time | async }}</div>
First of all,首先,
you're subscribing to getAllArticles()
in your onFormSubmit()
, why would you fetch all articles, assign the response to the local articles
and not use it?您在
getAllArticles()
订阅onFormSubmit()
,为什么要获取所有文章,将响应分配给本地articles
而不使用它? This code is a mess, 1st remove that subscription to getAllArticles()
, because it's out of context of creating a new article.这段代码一团糟,第一次删除对
getAllArticles()
订阅,因为它脱离了创建新文章的上下文。
onFormSubmit() {
console.log('articleafterdataSaved', this.articleForm.value);
this.dataSaved = false;
let article = this.articleForm.value; // not sure if that's the correct way to get the values either, but that's for another time.
this.createArticle(article);
this.articleForm.reset();
}
Then, I assume, you'd like to load all articles after that's done, for whatever reason.然后,我假设,无论出于何种原因,您都希望在完成后加载所有文章。 In your
createArticle()
function you're subscribing to the response of articleService.createArticle()
and updating dataSaved
and loading all articles.在
createArticle()
函数中,您订阅了articleService.createArticle()
的响应并更新dataSaved
并加载所有文章。
createArticle(article) {
console.log('articledataincreatearticle', article);
this.articleService.createArticle(article)
.subscribe(
Response => console.log('insubscribe-returned:', article),
this.dataSaved = true,
this.loadAllArticles()
);
}
however in this.loadAllArticles()
you're assigning allArticles$
to be articleService.getAllArticles()
但是在
this.loadAllArticles()
您将allArticles$
分配为articleService.getAllArticles()
loadAllArticles() {
this.allArticles$ = this.articleService.getAllArticles();
}
this of course does nothing unless subscribed.除非订阅,否则这当然什么都不做。
1st pass:第一关:
createArticle(article) {
console.log('articledataincreatearticle', article);
this.articleService.createArticle(article).pipe(
switchMap(response => {
console.log('insubscribe-returned:', response);
this.dataSaved = true;
return this.articleService.getAllArticles();
}
.subscribe(articles => this.articles = articles);
}
Here we introduced switchMap
and pipe()
To understand this, you have to look at the map() operator.这里我们介绍了
switchMap
和pipe()
要理解这一点,你必须看看 map() 操作符。 Observables are a stream of data. Observable 是一个数据流。 rxjs deals with streams of data.
rxjs 处理数据流。
You can pipe, just like you would in a linux or macos shell, operators and finally subscribe to the result.您可以使用管道,就像在 linux 或 macos shell 中一样,操作符并最终订阅结果。
Here we switched away from the stream of the articleService.createArticle()
Observable, did something inside the function (note the {}) and returned a new Observable stream, articleService.getAllArticles()
.这里我们从
articleService.createArticle()
Observable 的流中切换出来,在函数内部做了一些事情(注意 {})并返回一个新的 Observable 流, articleService.getAllArticles()
。 Then we do whatever with the response of this stream.然后我们对这个流的响应做任何事情。
2nd pass:第二关:
onFormSubmit() {
this.dataSaved = false;
const article = this.articleForm.value;
this.articleService.createArticle(article).pipe(
tap(data => console.log('response from createArticle:', data)),
tap(data => this.dataSaved = true),
switchMap(response => this.articleService.getAllArticles()),
tap(allArticlesData => console.log('all articles response:', allArticlesData)
).subscribe(articles => this.articles = articles)
}
So we did a bunch of stuff.所以我们做了一堆东西。 We
tap
ped into the stream to log the data.我们
tap
ped 进入流来记录数据。 We also used the tap
operator to change the dataSaved
state.我们还使用了
tap
运算符来更改dataSaved
状态。 We then switched away from the stream to return a new stream.然后我们从流切换到返回一个新流。 Tapped into that stream to console.log values.
进入该流以获取 console.log 值。 And finally assigned the response of that stream to the local articles member variable.
最后将该流的响应分配给本地文章成员变量。
And this is only the tip of the iceberg of issues with your code.这只是您的代码问题的冰山一角。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.