【问题标题】:Problems with getting angular 8 to post http request, Postman works fine获取 angular 8 来发布 http 请求的问题,邮递员工作正常
【发布时间】:2019-12-05 10:47:36
【问题描述】:

我在将数据发布到 API 后端时遇到了一些问题。该 API 可与 Postman 配合使用。

我有一个 Observable 服务,然后我在组件中订阅它。

我想做什么? 我正在尝试将 html 表单中的名字、姓氏和电子邮件地址发布到我的后端 api/数据库。如果我使用 Postman,它可以完美运行,所以我看不出问题出在 API 部分。 html 有一个调用 OnFormSubmit() 函数的表单。这又调用了 article.component.ts 中的 createArticle(article) 函数,它使用了 article.service.ts 文件中的 articleService.createArticle(article) 函数。当我运行 CreateArticle(article) 时,数据/值被传递并返回,但在后端 api 中,它们永远不会被写入。如果我使用 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

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 这是界面

export interface Article {
    id?: number;
    firstname: string;
    lastname: string;
    emailaddress: string;
}

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

<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>

【问题讨论】:

  • 您在组件中调用了哪个函数来“发布文章”?整个问题的代码到处都是。目前尚不清楚您要达到的目标。你想做什么?
  • 感谢您的浏览。我正在尝试将 html 表单中的名字、姓氏和电子邮件地址发布到我的后端 api/数据库。如果我使用 Postman,它可以完美运行,所以我看不出问题出在 API 部分。 html 有一个调用 OnFormSubmit() 函数的表单。这又调用了 article.component.ts 中的 createArticle(article) 函数,它使用了 article.service.ts 文件中的 articleService.createArticle(article) 函数。当我运行 CreateArticle(article) 时,数据/值被传递和返回,但在后端 api 中,它们永远不会被写入。
  • 什么意思:When I run the CreateArticle(article) the data/values are passed and returned but in the backend api, they are never written. 什么传到哪里,又从哪里返回。东西发送成功了吗?检查您的浏览器开发者控制台和网络选项卡是否有任何错误。这可能是 CORS 问题。
  • 嗨,谢谢 Fridoo,是的,我已经检查了我仍处于开发阶段的 CORS,所以它设置为 app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader( ));
  • 因此,当调用 createArticle (article) 函数时,'article' 中的值将传递给 articleService.createArticle(article),然后该函数将值发送到后端 localhost:5001:emailsub。当我检查数据库时,它添加了一个新的“文章”,但名字、姓氏和电子邮件地址是空白的。 id 被填充,带有一个数字,但其他三个我仍然有空值。当我签入 subscribe() 以查看值是否存在时,它们确实存在。请运行代码,它会告诉你我的意思。

标签: angular observable angular-httpclient subscribe


【解决方案1】:

首先,

您在onFormSubmit() 中订阅getAllArticles(),为什么要获取所有文章,将响应分配给本地articles 而不使用它? 这段代码很乱,第一次删除订阅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();
  }

然后,我假设您希望在完成后加载所有文章,无论出于何种原因。 在您的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()
    );

  }

但是在 this.loadAllArticles() 中,您将 allArticles$ 分配为 articleService.getAllArticles()

loadAllArticles() {
   this.allArticles$ = this.articleService.getAllArticles();
}

除非订阅,否则这当然什么都不做。

第一关:

  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);
  }

这里我们介绍了switchMappipe() 要理解这一点,您必须查看 map() 运算符。 Observables 是一个数据流。 rxjs 处理数据流。

您可以像在 linux 或 macos shell 中一样通过管道传输操作符并最终订阅结果。

在这里,我们从 articleService.createArticle() Observable 的流中切换出来,在函数内部做了一些事情(注意 {})并返回了一个新的 Observable 流 articleService.getAllArticles()。 然后我们对这个流的响应做任何事情。

第二遍:

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)
}

所以我们做了很多事情。 我们tapped 进入流以记录数据。 我们还使用tap 运算符来更改dataSaved 状态。 然后我们从流中切换到返回一个新流。 进入该流以获取 console.log 值。 最后将该流的响应分配给本地文章成员变量。

这只是代码问题的冰山一角。

【讨论】:

  • 非常感谢您抽出宝贵的时间。大部分代码来自我在尝试学习打字稿时使用的示例,角度 8。我将尝试将代码更改为您建议的内容。你能帮我理解为订阅输入什么吗,我真的很难理解在订阅方法中放入什么来检索数据并将其设置为变量,
  • 以及为什么数据存在​​于有效负载中并且没有添加到数据库中,如果我调试 api 应用程序,控制器中的变量为“null”。有人建议标题不正确,但据我所知,它是正确的吗?再次感谢您抽出宝贵时间提供帮助。
  • 我什至不知道 .cs 文件是什么语言。我在后端使用 Go
猜你喜欢
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多