NodeJS 后端从 Ionic 前端接收到空请求 body

NodeJS backend receives empty request body from Ionic frontend

我创建了一个带有 Node 后端的 Ionic 应用程序 (Angular2)。我的应用程序有一个叫做 Level 的东西,Level 有它的 title。我有一个带有加号的级别列表,它打开了一个用于添加新级别的模式。单击 "Save" 按钮时,模态消失,调用服务(Ionic 提供程序)方法,然后调用后端端点。

但是,我注意到存储在 MongoDB 中的每个文档都只有 ID 而没有标题。此外,我发现在调用后端之前一切都很好 - 如果我这样做 console.log,我可以看到已输入的标题。但是当我在后端输出请求时,请求中没有任何内容 body.

相关文件如下:

frontend/src/pages/admin-level-list/admin-level-list.ts

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ModalController } from 'ionic-angular';
import { LevelComponent } from '../../components/level/level';
import { LevelProvider } from '../../providers/level/level';
import { AddLevelPage } from '../add-level/add-level';
import { EditLevelPage } from '../edit-level/edit-level';

@IonicPage()
@Component({
  selector: 'page-admin-level-list',
  templateUrl: 'admin-level-list.html',
})
export class AdminLevelListPage {
  levels: any;    
  constructor(public navCtrl: NavController, public levelService: LevelProvider, public modalCtrl: ModalController) {    
  }

  ionViewDidLoad() {
    this.levelService.getLevels().then((data) => {
      this.levels = data;
      // The data is loaded correctly, but only with ID's, no titles
      // (because the titles are not stored in the DB at all)
    });
  }

  addLevel() {
    let modal = this.modalCtrl.create(AddLevelPage);
    modal.onDidDismiss(level => {
      if (level) {
        this.levels.push(level);
        this.levelService.createLevel(level);
      }
    });
    modal.present();
  }
}

frontend/src/pages/admin-level-list/admin-level-list.html

...
<button ion-button icon-only (click)="addLevel()">
  <ion-icon name="add"></ion-icon>
</button>
...

frontend/src/providers/level/level.ts

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable()
export class LevelProvider {
  data: any;

  constructor(public http: HttpClient) {
    this.data = null;
  }

  createLevel(level) {
    let headers = new HttpHeaders();
    headers.append('Content-Type', 'application/json');
    // ***** I'M LOGGING THE DATA HERE !!! *****
    console.dir(JSON.stringify(level));
    // ***** THE OUTPUT IS: *****
    // ***** {"title":"Exactly what I have entered"} *****
    // ***** ...SO I GUESS ALL IS FINE UNTIL NOW *****
    this.http.post('http://localhost:8080/api/levels', JSON.stringify(level), { headers: headers })
      .subscribe(res => {
        console.dir(res);
      });
  }
}

frontend/src/pages/add-level/add-level.ts

import { Component } from '@angular/core';
import { IonicPage, ViewController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-add-level',
  templateUrl: 'add-level.html',
})
export class AddLevelPage {
  title: any;
  constructor(public viewCtrl: ViewController) {
  }

  save(): void {
    let level = {
      title: this.title
    };
    this.viewCtrl.dismiss(level);
  }

  close(): void {
    this.viewCtrl.dismiss();
  }
}

frontend/src/pages/add-level/add-level.html

<ion-content>
  <ion-list no-lines>
    <ion-item>
      <ion-label floating>Title</ion-label>
      <ion-input [(ngModel)]="title" type="text"></ion-input>
    </ion-item>
  </ion-list>
  <button ion-button full color="secondary" (click)="save()">Save</button>
</ion-content>

backend/server.js

var express = require('express');
var app = express();
var mongoose = require('mongoose');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var cors = require('cors');

mongoose.connect('mongodb://localhost/kursnemackog');

app.use(morgan('dev')); 
app.use(bodyParser.urlencoded({ 'extended': 'true' })); 
app.use(bodyParser.json());   
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); 
app.use(methodOverride());
app.use(cors());

app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header('Access-Control-Allow-Methods', 'DELETE, PUT');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

var Level = mongoose.model('Level', {
    title: String
});

app.post('/api/levels', function (req, res) {
    // ***** I'M LOGGING THE REQUEST HERE !!! *****
    console.log(req);
    // ***** ITS BODY IS EMPTY !!!!! *****
    // ***** IncomingMessage {       *****
    // ***** ...                     *****
    // ***** params: {},             *****
    // ***** query: {},              *****
    // ***** ...                     *****
    // ***** body: {},               *****
    // ***** ...                     *****
    Level.create({
        title: req.body.title,
        done: false
    }, function (err, level) {
        if (err)
            res.send(err);
        Level.find(function (err, levels) {
            if (err)
                res.send(err)
            res.json(levels);
        });
    });
});

// listen (start app with node server.js) ======================================
app.listen(8080);

有谁知道为什么什么都没有传递到后端? 如果您需要任何其他 data/code 片段,请告诉我。

解决了!在level.ts而不是发送JSON.stringify(level),我只发送level,现在正文中有title字段。