Search code examples
c#jsonhttpangularangular2-services

Angular2 reading JSON


I have the following GET method for the UsersController

public IEnumerable<object> Get()
{
    var con = _context.Database.GetDbConnection();
    var cmd = con.CreateCommand();
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "sp_Users";
    cmd.Parameters.Add(new SqlParameter("@Command", SqlDbType.VarChar) { Value = "GetUsers" });

    var retObject = new List<dynamic>();
    con.Open();
    using (var dataReader = cmd.ExecuteReader())
    {
        while (dataReader.Read())
        {
            var dataRow = new ExpandoObject() as IDictionary<string, object>;
            for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
                dataRow.Add(
                    dataReader.GetName(iFiled),
                    dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
                );

            retObject.Add((ExpandoObject)dataRow);
        }
    }
    return retObject;
}

I tested it in postmanand it worked perfectly returning:

[{"UserID": 1, "UserName": "foo"}, {"UserID": 2, "UserName": "bar"}]

Now I want to display them with angular2, so I coded a service user.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';

@Injectable()
export class UsersService {
    student: any;
    constructor(private http: Http) { }

    getUsers() {
        return this.http.get('api/users')
            .map((res: Response) => <string[]>res.json()); 
    }
}

And at home.component.ts I have:

ngOnInit() {
    this.usersService.getUsers()
        .subscribe(users=> this.users = users);
    console.log(this.users);
}

But I get the following error:

core.umd.js:3462 EXCEPTION: Unexpected token < in JSON at position 0ErrorHandler.handleError @ core.umd.js:3462next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runTask @ zone.js:139ZoneTask.invoke @ zone.js:304
core.umd.js:3467 ORIGINAL STACKTRACE:ErrorHandler.handleError @ core.umd.js:3467next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runTask @ zone.js:139ZoneTask.invoke @ zone.js:304
core.umd.js:3468 SyntaxError: Unexpected token < in JSON at position 0
    at Function.Json.parse (http.umd.js:188)
    at Response.Body.json (http.umd.js:1166)
    at MapSubscriber.eval [as project] (character.service.ts:11)
    at MapSubscriber._next (map.ts:79)
    at MapSubscriber.Subscriber.next (Subscriber.ts:95)
    at XMLHttpRequest.onLoad (http.umd.js:1497)
    at ZoneDelegate.invokeTask (zone.js:236)
    at Object.onInvokeTask (core.umd.js:6233)
    at ZoneDelegate.invokeTask (zone.js:235)
    at Zone.runTask (zone.js:136)ErrorHandler.handleError @ core.umd.js:3468next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runTask @ zone.js:139ZoneTask.invoke @ zone.js:304
Subscriber.ts:241 Uncaught SyntaxError: Unexpected token < in JSON at position 0

Solution

  • I fixed with the following:

    import { Injectable } from '@angular/core';
    import { Http, Response } from '@angular/http';
    import { Observable }     from 'rxjs/Observable';
    
    @Injectable()
    export class UsersService {
    
        constructor(private http: Http) { }
    
        getUsers(): Observable<any[]> {
            return this.http.get('api/users')
                        .map(this.extractData)
                        .catch(this.handleError);
            }
            private extractData(res: Response) {
                console.log(res);
                let body = res.json();
                return body.data || { };
            }
            private handleError (error: any) {
                // In a real world app, we might use a remote logging infrastructure
                // We'd also dig deeper into the error to get a better message
                let errMsg = (error.message) ? error.message :
                error.status ? `${error.status} - ${error.statusText}` : 'Server error';
                console.error(errMsg); // log to console instead
                return Observable.throw(errMsg);
            }
    }