Handle 400 Bad Request From WebApi In Angular 6 (using HttpClient)

27,263

Solution 1

I was also facing the same problem in angular 7. However I fixed this today using below code :

In service :

registerUser(userdata): Observable<any> {
    return this.httpClient.post('url', userdata).pipe(catchError(this.handleError));
}

handleError(error: HttpErrorResponse) {
    return throwError(error);
}

In register.component.ts :

postData() {
    this.auth.registerUser(userdata).subscribe(
        (resp) => {
            console.log(resp);
        },
        (error) => {
            console.log(error.error);
        }
    );
}

Solution 2

Dotnet Core 400 Identity error response is an array of {code,description}. So to handle it in typescript, first define an interface(not required actually,but for strict type checking.

interface ClientError {
    code: string;
    description: string;
}

Then in the part where you handle error, do following,

(error:HttpErrorResponse) => { 
   if(error.status===400){            
      const errors: Array<ClientError> = error.error;
      errors.forEach(clientError => {
         console.log(clientError.code);
      });
   }
}

Update: This is specific to Identity Framework. (Login and Registration). In other areas, Error Handling will need a manual work to align with this pattern.

Share:
27,263

Related videos on Youtube

Jason
Author by

Jason

Updated on May 24, 2021

Comments

  • Jason
    Jason almost 3 years

    Below is an Asp.net Core WebAPI which returns bad request with Error details as to its param when let's say duplicate a user is trying to register.

    public async Task<IActionResult> Register([FromBody] RegisterModel registerModel)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser
                {
                    //TODO: Use Automapper instead of manual binding  
    
                    UserName = registerModel.Username,
                    FirstName = registerModel.FirstName,
                    LastName = registerModel.LastName,
                    Email = registerModel.Email
                };
                var identityResult = await this.userManager.CreateAsync(user, registerModel.Password);
                if (identityResult.Succeeded)
                {
                    await signInManager.SignInAsync(user, isPersistent: false);
                    return Ok(GetToken(user));
                }
                else
                {
                    Console.WriteLine("Errors are : "+ identityResult.Errors);
                    return BadRequest(identityResult.Errors);
                }
            }
            return BadRequest(ModelState);
    

    The response is being handled at the Angular side as follows:

    user.service.ts

    register(user: User) {
       // let headers = new Headers({ 'Content-Type': 'application/json' });
       //var reqHeader = new HttpHeaders({ 'Content-Type': 'application/json'});
       const reqHeader = new HttpHeaders().set('Content-Type', 'application/json')
                                .set('Accept', 'application/json');
    //return this.http.post(this.rootUrl + '/api/account/register', body,{headers : reqHeader});
    
        return this.http.post(this.apiUrl+ '/api/account/register', user,{headers : reqHeader});
    }
    

    above method being called out in:

    register.component.ts

    this.userService.register(this.registerForm.value)
            .pipe(map((res: Response) => res.json()))
            .subscribe(
                data => {
                    this.alertService.success('Registration successful', true);
                    this.router.navigate(['/login']);
                },
                (error:HttpErrorResponse) => {
                    // let validationErrorDictionary = JSON.parse(error.text());
                    // for (var fieldName in validationErrorDictionary) {
                    //     if (validationErrorDictionary.hasOwnProperty(fieldName)) {
                    //         this.errors.push(validationErrorDictionary[fieldName]);
                    //     }
                    // }
                    // this.alertService.errorMsg(this.errors);
                    console.log(error.error);
                });
    

    When I tried to do Postman I get perfect result as below :

    Postman Result: Screenshot 1

    But the same result despite trying multiple code snippet doesn't work out and all it logs 'Bad result' as a response.

    Angular Result: Screenshot 2

    I did notice though the response lies in the network tab.. just short of an idea to process it.

    Error Description: Screenshot 3

    What's missing here? your response will be much appreciated !

  • Jason
    Jason over 5 years
    Refereed it too.. No Qualms with status code I am interested in error description it rendered at Postman. The problem, in the name of error I only see just a text "Bad result" at client. Nothing more !
  • aledpardo
    aledpardo over 5 years
    Couldn't the client have a Proxy which intercepts the error responses?
  • n.prokhorov
    n.prokhorov over 5 years
    @Jason let errorPayload = JSON.parse(error.message) what is value of this in debugger? And what is state of (error:HttpErrorResponse) =>... argument object? Please provide a dump of this objects
  • Jason
    Jason over 5 years
    @n.piskunov errorPayload = JSON.parse(error.message) results in 'Undefined'. and same happens with (errr:HttpErrorRrsponse...). some more screenshots are mentioned at github.com/angular/angular/issues/26817. However I noticed Expected outcome with Http and not with HttpClient (why so ?). Will post soon more details.