2
votes

I have created a simple test class to use to make my http request to an OData API (both running on my local machine, with CORs enabled). My OData Service looks like so:

import { Injectable } from '@angular/core';

import { Http, Response, RequestOptionsArgs, Headers } from '@angular/http';

import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';

import { IUrlOptions } from './odata.model';
import { RequestTypes } from './odata.model';

@Injectable()
export class ODataService {

    constructor(
        private host: string,
        private http: Http
    ) {  }


    private constructUrl(urlOptions: IUrlOptions): string {
        return this.host + urlOptions.restOfUrl;
    }



    //T specifies a generic output of function
    public Request<T>(requestType: RequestTypes, urlOptions: IUrlOptions, body?: any, options?: RequestOptionsArgs) : Observable<T> {
        let response: Observable<Response>;

        if(requestType == RequestTypes.delete){
            response = this.http.delete(this.constructUrl(urlOptions), options);
        } else if(requestType == RequestTypes.get){

            response = this.http.get(this.constructUrl(urlOptions), options);
        } else if (requestType == RequestTypes.post){
            response = this.http.post(this.constructUrl(urlOptions), body, options)
        }

        return response.map((res) => <T>res.json());
    }
}

Now i have a component to test this service:

import { Component, OnInit } from '@angular/core';

import { ODataService } from './odata.service';
import { RequestTypes } from './odata.model';
import { IUrlOptions } from './odata.model';

import  { Template } from '../../models/template.model' 

@Component({
    selector: 'odata',
    templateUrl: 'odata.component.html'
})
export class ODataComponent implements OnInit {


    public requestResult: any;

    constructor(
        private odata: ODataService
    ) { }

    ngOnInit() { }

    testGet() {
        let urlOptions: IUrlOptions = <IUrlOptions>{};
        urlOptions.restOfUrl = "Template";
        this.odata.Request(RequestTypes.get, urlOptions).subscribe(
            data => this.requestResult = data,
            error => alert(error)
        );
    }

    testPost() {
        let urlOptions: IUrlOptions = <IUrlOptions>{};
        urlOptions.restOfUrl = "Template";
        let body = new Template();
        body.Name = "Test3";
        body.Private = false;
        body.User = "chp";

        let jsonBody = JSON.stringify(body);

        this.odata.Request(RequestTypes.post, urlOptions, jsonBody).subscribe(
            data => this.requestResult = data,
            error => alert(error)
        );
    }

    testPut() {
        let urlOptions: IUrlOptions = <IUrlOptions>{};
        this.odata.Request(RequestTypes.put, urlOptions).subscribe(
            data => this.requestResult = data,
            error => alert(error)
        );
    }

    testPatch() {
        let urlOptions: IUrlOptions = <IUrlOptions>{};
        this.odata.Request(RequestTypes.patch, urlOptions).subscribe(
            data => this.requestResult = data,
            error => alert(error)
        );
    }

    testDelete() {
        let urlOptions: IUrlOptions = <IUrlOptions>{};
        urlOptions.restOfUrl = "Template(6)"
        this.requestResult = this.odata.Request(RequestTypes.delete, urlOptions);
    }

}

Ignoring the Put and Patch as they have not been implemented the only service that seems to work is GET. POST and DELETE does not seem to work at all; calling DELETE http://localhost:53219/Template(6) should delete the Template with ID 6, which works when done using SOAP UI but not using the this.http.delete(...) function defined in the first code snippet.

Furthermore looking at the network recordings on chrome it does not look like a delete request is ever made, am I missing something to call the function?

My SOAP UI Request is as follows:

DELETE http://localhost:53219/Template(6) HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/json
Content-Length: 83
Host: localhost:53219
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

Any help would be appreciated

1

1 Answers

0
votes

This ended up being a Header/CORs issue. I did the following steps to fix it:

  1. Added following Headers to my requests:
let headers = new Headers();
headers.append("OData-Version","4.0");
headers.append("Content-Type","application/json;odata.metadata=minimal");
headers.append("Accept","application/json");
return headers;
  1. Then I also had to expose headers on my OData API server as Chrome and other newer browsers do some "pre-flight" stuff that sends out a OPTIONS request (find out more here). To do this I added the following in my WebApiConfi.cs:
 var cors = new EnableCorsAttribute(origins: "*", headers: "*", methods: "*", exposedHeaders: "*");
            config.EnableCors(cors);

this enables CORS on all Controllers, you can specify it on individual Controllers or Methods as mentioned in the link above.