angularasp.net-core-webapihttp-postfrombodyattribute

Null parameter is passed to API controller after post request sent from Angular frontend


I developed a login function in the backend

[Route("api/")]
[ApiController]
public class LoginController : ControllerBase
{
    private readonly ILoginService _loginService;

    public LoginController(ILoginService loginService)
    {
        _loginService = loginService;
    }

    [HttpPost("login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login([FromBody]UserForRouteDto resource, CancellationToken cancellationToken)
    {
        try
        {
            var response = await _loginService.Login(resource, cancellationToken);
            return Ok(response);
        }
        catch (Exception e)
        {
            return BadRequest(new { ErrorMessage = e.Message });
        }
    }
}

The UserForRouteDto class is designed as

public class UserForRouteDto
{
    public string? Username { get; set; }
    public string? Password { get; set; }
    public string? Role { get; set; }

    public UserForRouteDto()
    {
            
    }
}

The frontend is developed by my colleague. I have no experience in Angular so I just paste the code here.

import { Injectable } from '@angular/core';
import { User } from '../models/user';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  
  private apiUrl = "https://localhost:7213"
  constructor(
    private http: HttpClient
  ) { }

  getLoginDetails(userDetails:User): Observable<void>{
    return this.http.post<void>(this.apiUrl+'/login',  userDetails);
  }
}

The User class is designed as

export interface User {
    Username: string,
    Password: string
    Role: string
}

Then after launching the backend and frontend, I click login button and backend gets fired. But the parameter resource is null.

I have tried lots of solution found online but none of them works for me. I have tried to remove [FromBody] attribute and change the getLoginDetails into

getLoginDetails(userDetails:User): Observable<string>{
    const headers = { 'content-type': 'application/json'}  
    const body=JSON.stringify(userDetails);
    return this.http.post<string>(this.apiUrl+'login',  body,{'headers':headers});
  }

But I still get null value. Then I changed the argument in the login function in backend using HttpRequestMessage class. Funny is, though I get null content, the method shows GET insead of expected POST.

Another thing bothers me is, I can only access to the page under the url http://localhost:4200. The url http://localhost:4200/login or http://localhost:4200/api/login does not work. I have spent lots of time on this but sill no clue. Could someone help?


Solution

  • After another hundreds of testing, I found the solution. The method in frontend should be

    getLoginDetails(userDetails:User): Observable<User>{     
        const headers = { 'content-type': 'application/json'}       
        return this.http.post<User>(this.apiUrl+'/login', userDetails {'headers':headers});   
    }
    

    It seems that using this way the backend can receive request content.