Click here to Skip to main content
14,699,489 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have an angular project where I implemented a login function in the login.service.ts.My problem is that no matter what I do I can't get rid of the 405 error Method not Allowed for POST.When I check Postman for the API it gives me the same error and it displays only DELETE and PUT as allowed methods.This is the service class:
import { Injectable } from '@angular/core';
import {Register} from '../Models/register';
import { HttpClient, HttpHeaders, HttpErrorResponse} from '@angular/common/http';
import { BehaviorSubject, Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
@Injectable({
  providedIn: 'root'
})
export class LoginService {
  headers = new HttpHeaders().set('Content-Type', 'application/json;charset=utf-8').append('Authorization', 'Bearer');

  currentUser = {};
ApiUrl = 'https://localhost:5001';
    constructor(private http: HttpClient, public router: Router) {
    }
    login(user: Register) {
      return this.http.post(this.ApiUrl + '/register/login', user)
        .subscribe((res: any) => {
          localStorage.setItem('access_token', res.token);
          // tslint:disable-next-line:no-shadowed-variable
          this.getUserProfile(res.id).subscribe((res) => {
            this.currentUser = res;
            this.router.navigate(['/register/userdata/' + res.msg.id]);
          });
        });
    }
    getToken() {
      return localStorage.getItem('access_token');
    }
   get isLoggedIn(): boolean {
      const authToken = localStorage.getItem('access_token');
      return (authToken !== null) ? true : false;
    }

    doLogout() {
      const removeToken = localStorage.removeItem('access_token');
      if (removeToken == null) {
        this.router.navigate(['login']);
      }
    }

    // User profile
    getUserProfile(id): Observable<any> {
      const api = this.ApiUrl + 'register/userdata/' + id;
      return this.http.get(api, { headers: this.headers }).pipe(
        map((res: Response) => {
          return res || { };
        }),
        catchError(this.handleError)
      );
    }

    handleError(error: HttpErrorResponse) {
      let msg = '';
      if (error.error instanceof ErrorEvent) {
        // client-side error
        msg = error.error.message;
      } else {
        // server-side error
        msg = `Error Code: ${error.status}\nMessage: ${error.message}`;
      }
      return throwError(msg);
    }
}



This is the login.component.ts:
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { LoginService } from '../services/login.service';
import { first } from 'rxjs/operators';
import {ToastrManager} from 'ng6-toastr-notifications';
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
  constructor(private formBuilder: FormBuilder,
    private route: ActivatedRoute,
    private router: Router,
    private loginService: LoginService,
    public toast: ToastrManager, ) { }

  ngOnInit() {
    this.loginForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
    });
  }
get loginFormControl() {return this.loginForm.controls; }
onSubmit() {
  this.submitted = true;

  // stop here if form is invalid
  if (this.loginForm.invalid) {
  return;
  }
  this.loading = true;
    this.loginService.login(this.loginForm.value);
    this.toast.successToastr('Its working');
  this.router.navigate(['register/userdata/id']);
 }
}

I recreated a couple of versions from the internet with the client side authentication but gave me the same error over and over no matter what version I used.
I have no clue why it's not working,I'm struggling for some time with the error and I tried almost every possible combination to make it work.Does someone have any idea about this problem and how can be resolved? Any help would be appreciated!!!



UPDATE:
This is the server controller class:
[EnableCors]
  [Authorize]
  [ApiController]
  [Produces("application/json")]
  [Route("[controller]")]
  public class LoginController : ControllerBase
  {
      private readonly IConfiguration _config;
      public LoginController(IConfiguration config)
      {
          _config = config;
      }
      private List<Register> appUsers = new List<Register>();
      [AllowAnonymous]
      [HttpPost]
      [Route("login")]
      public IActionResult Login([FromBody] Register model)
      {
          IActionResult response = Unauthorized();
          Register user = AuthenticateUser(model);
          if (user != null)
          {
              var tokenString = GenerateJWT(user);
              response = Ok(new
              {
                  token = tokenString,
                  userDetails = user,
              });
          }
          return response;
      }

     string GenerateJWT(Register user)
      {
          var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"]));
          var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

          var claims = new[]
          {
              new Claim(JwtRegisteredClaimNames.Sub, user.Email),
              new Claim("Name", user.Name.ToString()),
              new Claim("role",user.Role),
              new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
          };

          var token = new JwtSecurityToken(
              issuer: _config["Jwt:Issuer"],
              audience: _config["Jwt:Audience"],
              claims: claims,
              expires: DateTime.Now.AddMinutes(30),
              signingCredentials: credentials
          );
          return new JwtSecurityTokenHandler().WriteToken(token);
      }

      Register AuthenticateUser(Register login)
      {
         Register user = appUsers.SingleOrDefault(x => x.Email == login.Email && x.Password == login.Password);
          return user;
      }
  }


This is the Register.cs class:
public class Register
   {
       public string Role { get; set; }
       public string Name { get; set; }
       [Key]
       public int Id { get; set; }
       public string Email { get; set; }
       public string Password { get; set; }

   }


What I have tried:

I tried to assign email and password to the function and get their values with JSON.stringify(),I tried to change the header to allow POST method but then I realised I already did that in my CORS middleware class to which method I pass it in Startup.cs.(server side).When I put breakpoints to debug it,I have no problem with it as it actually reads the info inputted but in login.service.ts when I hit the breakpoint at
localStorage.setItem('access_token', res.token);
on localStorage it gives me the length 0 and after isLoggedIn boolean is set to false as it won't login.I don't know how relevant is this but I also get this upon setting breakpoints(when i look at methods):
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them.

I understood that this is usually caused by the syntax 'use strict' but I don't have any js I have to worry about.
Posted
Updated 12-Mar-20 4:54am
v3

1 solution

Good morning,
Based on the code 405 method not allowed, it looks like you have to enable the verb POST in the configuration of the ASP.Net Web API. Could you please refer the below link for additional details. Also please resue that you have the [HttpPost] method available inside the Web API code with appropriate parameters. Many thanks.

Looks like the issue is with the route you are using in .ts file.
return this.http.post(this.ApiUrl + '/register/login', user)

I assume it should be "/login/login" instead of "/register/login". Becuase your API method has only [Route("login")] has route. Many thanks.
return this.http.post(this.ApiUrl + '/login/login', user)


I have tested the code on my Laptop using Postman

Troubleshoot Web API2 apps that work in Visual Studio and fail on a production IIS server | Microsoft Docs[^]
   
v6
Comments
Eliza Maria 12-Mar-20 8:05am
   
Thank you for your response!Unfortunately I don't have the project with .aspx file extension,I work with the default angular project which does not contain a applicationHost.config file.I also have [HttpPost] method on the server side in the controller and the route set like this:Route[("login")].
Viswanatha Swamy 12-Mar-20 8:36am
   
@Eliza Maria,
Good evening. Based on the URL https://localhost:5001 it looks like you are executing the Web Api on the Local Laptop. The configuration should be done on the ASP.Net Web API side. Could you please hit the API endpoint using postman to see what output is given.

Viswanatha Swamy 12-Mar-20 9:31am
   
@Eliza Maria,
Good evening. Could you please try sending the logic values using Postman to the /register/login endpoint? That will help us see what output is returned from that endpoint.
Eliza Maria 12-Mar-20 9:39am
   
Thank you for your help.It gives me the same error as in the browser which is 405 method not allowed and when i am trying to send the values it will not give any output for some reason...
Viswanatha Swamy 12-Mar-20 9:41am
   
@Eliza,
Good evening. So the two experiments point the Web API. Is this Web API Developed in .Net Framework OR .Net Core? Is it being executed in Kestrel Server OR IIS Express OR IIS? Please advise.
Eliza Maria 12-Mar-20 9:44am
   
I am using .Net Core with Kestrel
Eliza Maria 12-Mar-20 9:47am
   
The thing is that on the server side everything is in order.I set the properties of the controller by enabling CORS and the route for the api so there should not be any problem.As far as I understood and please correct me if I am wrong, this error has sth to do with the client side.
Viswanatha Swamy 12-Mar-20 9:53am
   
@Eliza,
I the server-side the up and running. I assume it should work when we use a postman. Please advise if your postman is going through?
Viswanatha Swamy 12-Mar-20 9:48am
   
@Eliza,
Good evening. Could you please just post the method signature? It will be helpful to have the Attributes too. Many thanks.
Eliza Maria 12-Mar-20 9:52am
   
Done!Please let me know if you need any additional info and again thank you for your help :)
Viswanatha Swamy 12-Mar-20 9:58am
   
I am working on it. Let me try your code on my laptop and let you know. Give me some time. Many thanks.
Eliza Maria 12-Mar-20 10:01am
   
ok sure!Thank you so much for your help!
Viswanatha Swamy 12-Mar-20 10:05am
   
Looks like the issue is with the route you are using in .ts file.
return this.http.post(this.ApiUrl + '/register/login', user)

I assume it should be "/login/login" instead of "/register/login". Becuase your API method has only [Route("login")] has route. Many thanks.
return this.http.post(this.ApiUrl + '/login/login', user)
Eliza Maria 12-Mar-20 10:23am
   
Wow thanks!I can see that you're right.When I do that I get 401 Unauthorized access which means that the path is actually the good one.I forgot I am using the login controller and not the register controller.Thank you so much for all your help!!!Best regards!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900