TrevorBrooks TrevorBrooks - 3 years ago 225
JSON Question

Response is undefined

I've followed the Heroes tutorial and I am now attempting to retrieve my hero data from an MVC web api rest service. I have modified the

GetHeroes()
method in my hero.service:

import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';

import { HttpClient } from '@angular/common/http';

export class Hero {
constructor(public Id: number, public HeroName: string, public Location: string) { }
}

@Injectable()
export class HeroService {

constructor(private http: HttpClient) { }

results: Observable<string[]>;

private location: string;

getHeroes(): Observable<Hero[]> {
return this.http.get('http://localhost:50125/api/heroes')
.map((response: Response): Hero[] => JSON.parse(response['_body']))
.catch(error => Observable.throw(error));
}

getHero(id: number | string) {
return this.getHeroes()
// (+) before `id` turns the string into a number
.map(heroes => heroes.find(hero => hero.Id === +id));

}

}


I am calling the service method from my component:

import 'rxjs/add/operator/switchMap';
import { Observable } from 'rxjs/Observable';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';

import { Hero, HeroService } from './hero.service';

@Component({
template: `
<h2>HEROES</h2>
<ul class="items">
<li *ngFor="let hero of heroes$ | async"
[class.selected]="hero.Id === selectedId">
<a [routerLink]="['/hero', hero.Id]">
<span class="badge">{{ hero.Id }}</span>{{ hero.HeroName }}
</a>
</li>
</ul>
`
})
export class HeroListComponent implements OnInit {
heroes$: Observable<Hero[]>;

private selectedId: number;

constructor(
private service: HeroService,
private route: ActivatedRoute
) {}

ngOnInit() {
this.heroes$ = this.route.paramMap
.switchMap((params: ParamMap) => {
// (+) before `params.get()` turns the string into a number
this.selectedId = +params.get('id');
return this.service.getHeroes();
});
}

}


My Heroes api controller looks like this:

using HeroesService.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json;

namespace HeroesService.Controllers
{
public class HeroesController : ApiController
{
// GET: api/Heroes
public List<Hero> Get()
{
List<Hero> heroes = new List<Hero>();

Hero superman = new Hero();
superman.Id = 10;
superman.HeroName = "Superman";
superman.Location = "Los Angeles, California";
heroes.Add(superman);

Hero batman = new Hero();
batman.Id = 11;
batman.HeroName = "Batman";
batman.Location = "Chicago, Illinois";
heroes.Add(batman);

return heroes;
}
}
}


I can see data in the Chrome's Network tab that looks like this:

[{"Id":10,"HeroName":"Superman","Location":"Los Angeles, California"},{"Id":11,"HeroName":"Batman","Location":"Chicago, Illinois"}]


Unfortunately, I get an error that looks like this (probably means the response data is undefined):


ERROR SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse ()
at MapSubscriber.eval [as project] (hero.service.ts:34)
at MapSubscriber._next (map.ts:75)
at MapSubscriber.Subscriber.next (Subscriber.ts:95)
at MapSubscriber._next (map.ts:80)
at MapSubscriber.Subscriber.next (Subscriber.ts:95)
at FilterSubscriber._next (filter.ts:95)
at FilterSubscriber.Subscriber.next (Subscriber.ts:95)
at MergeMapSubscriber.notifyNext (mergeMap.ts:151)
at InnerSubscriber._next (InnerSubscriber.ts:17)

Answer Source

You can take advantage of the fact that HttpClient.get is able to work with JSON data for you. Use the following code to tell HttpClient that the response type is Hero[] and drop your calls to both map and catch:

 return this.http.get<Hero[]>('http://localhost:50125/api/heroes');

I expect you are getting an undefined due to the fact that response will not have a property _body.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download