Angular post request body is null when received by Spring API - Stack Overflow

时间: 2025-01-06 admin 业界

I am submitting a request from a simple Angular app to test a Spring endpoint I have made. The same JSON is processed successfully when I submit it through Postman, so I suspect that there is something wrong on the Angular side. Here is what the front and backend look like:

tft-calculator.service.ts:

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

@Injectable({
  providedIn: 'root'
})
export class TftCalculatorService {
  apiUrl = 'http://localhost:8080'
  constructor(private http: HttpClient) { }

  calculateChanceOfHitting(){
    let data: object;
    data = {"name":"Mordekaiser",
      "targetCount":3,
      "currentUnits":0,
      "sameUnitOnOtherBoards":0,
      "currentLevel":8,
      "currentGold": 130,
      "prismaticTicket": false};
    let params = new HttpParams().set("requestData", JSON.stringify(data));
    console.log(params);
    let headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8');;
    return this.http.post<any[]>(`${this.apiUrl}/calculateChanceOfHitting`,
      {params: data,
      headers: headers});
  }
}

TFTController.java:

package com.example.gamingcalculator;

import com.example.gamingcalculator.pojo.CalculatorParams;
import com.example.gamingcalculator.pojo.Unit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@CrossOrigin(origins = "*")
public class TFTController {

    @Autowired
    TFTService tftService;

    @GetMapping("/calculateGoldNeeded")
    @ResponseBody
    public int calculateGoldNeeded(@RequestBody CalculatorParams params) {
        return tftService.calculateGoldNeeded(params.getName(),
            params.getTargetCount(),
            params.getCurrentUnits(),
            params.getSameUnitOnOtherBoards(),
            params.getCurrentLevel());
    }

    @PostMapping("/calculateChanceOfHitting")
    @ResponseBody
    public double calculateChanceOfHitting(@RequestBody CalculatorParams params) {
        return tftService.calculateChanceOfHitting(params.getName(),
                params.getTargetCount(),
                params.getCurrentUnits(),
                params.getSameUnitOnOtherBoards(),
                params.getCurrentLevel(),
                params.getCurrentGold(),
                params.isPrismaticTicket());
    }
}

Here is what the HTTP request looks like from the front end

And here are the parameters from a debug line immediately after the controller is hit

I have tried changing the formatting of the JSON, but I suspect that there is something particular in the Angular that I'm missing.

I am submitting a request from a simple Angular app to test a Spring endpoint I have made. The same JSON is processed successfully when I submit it through Postman, so I suspect that there is something wrong on the Angular side. Here is what the front and backend look like:

tft-calculator.service.ts:

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

@Injectable({
  providedIn: 'root'
})
export class TftCalculatorService {
  apiUrl = 'http://localhost:8080'
  constructor(private http: HttpClient) { }

  calculateChanceOfHitting(){
    let data: object;
    data = {"name":"Mordekaiser",
      "targetCount":3,
      "currentUnits":0,
      "sameUnitOnOtherBoards":0,
      "currentLevel":8,
      "currentGold": 130,
      "prismaticTicket": false};
    let params = new HttpParams().set("requestData", JSON.stringify(data));
    console.log(params);
    let headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8');;
    return this.http.post<any[]>(`${this.apiUrl}/calculateChanceOfHitting`,
      {params: data,
      headers: headers});
  }
}

TFTController.java:

package com.example.gamingcalculator;

import com.example.gamingcalculator.pojo.CalculatorParams;
import com.example.gamingcalculator.pojo.Unit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@CrossOrigin(origins = "*")
public class TFTController {

    @Autowired
    TFTService tftService;

    @GetMapping("/calculateGoldNeeded")
    @ResponseBody
    public int calculateGoldNeeded(@RequestBody CalculatorParams params) {
        return tftService.calculateGoldNeeded(params.getName(),
            params.getTargetCount(),
            params.getCurrentUnits(),
            params.getSameUnitOnOtherBoards(),
            params.getCurrentLevel());
    }

    @PostMapping("/calculateChanceOfHitting")
    @ResponseBody
    public double calculateChanceOfHitting(@RequestBody CalculatorParams params) {
        return tftService.calculateChanceOfHitting(params.getName(),
                params.getTargetCount(),
                params.getCurrentUnits(),
                params.getSameUnitOnOtherBoards(),
                params.getCurrentLevel(),
                params.getCurrentGold(),
                params.isPrismaticTicket());
    }
}

Here is what the HTTP request looks like from the front end

And here are the parameters from a debug line immediately after the controller is hit

I have tried changing the formatting of the JSON, but I suspect that there is something particular in the Angular that I'm missing.

Share Improve this question edited yesterday jonrsharpe 122k30 gold badges263 silver badges469 bronze badges asked yesterday alexander acevedoalexander acevedo 9 New contributor alexander acevedo is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 2
  • 1 You're mixing up body and options: angular.dev/guide/http/making-requests#mutating-server-state. Also, in the options, params is for URL (search/query) parameters, not the request body: angular.dev/guide/http/making-requests#setting-url-parameters. Look at what the network tab is showing - the "headers" are in the body. – jonrsharpe Commented yesterday
  • Your headers and params should go in the third parameter which is options.. Just send {...data} in your second param. – rakesh shrestha Commented yesterday
Add a comment  | 

1 Answer 1

Reset to default 0

Couple of changes

  1. Send object as body instead of params. Params is only for query params
  2. You don't need to set headers as JSON, because by default it's JSON
import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from "@angular/common/http";

@Injectable({
  providedIn: 'root'
})
export class TftCalculatorService {
  apiUrl = 'http://localhost:8080'
  constructor(private http: HttpClient) { }

  calculateChanceOfHitting(){
    const data = {"name":"Mordekaiser",
      "targetCount":3,
      "currentUnits":0,
      "sameUnitOnOtherBoards":0,
      "currentLevel":8,
      "currentGold": 130,
      "prismaticTicket": false};

    return this.http.post<any[]>(`${this.apiUrl}/calculateChanceOfHitting`,data);
  }
}
最新文章