Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using HttpClient and RXJS to POST data to Web API withCredentials: true

I’ve got an Angular service that I’ve connected to my .NET Web API, and I’m trying to POST some data to the API. Currently I'm using HTTP rather than HttpClient, and I'm not sending any data. But the service is successfully connecting to the API.

I need help with passing actual data through from my Angular controller to the service (and thus to the API), and also implementing HttpClient in the service. So far my controller just calls my service's myFunction() function and doesn’t pass it any parameters, thus no data. I’m unsure where in the RXJS portion of the service to append my data.

Note: however I implement this, I still need it to pass withCredentials: true, due to to the configuration of my API

Web API Controller:

namespace api.controllers
{
    [Authorize]
    public class ValuesController : ApiController
     {
        static List<string> strings = new List<string>()
        {
            "value0", "value1", "value2"
        };

        // GET api/values
        public IEnumerable<string> Get()
        {
            return strings;
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        public void Post([FromBody]string value)
        {
            strings.Add(value);
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }

    }
}

Web API web.config file (CORS settings):

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="http://localhost:5200" />
    <add name="Access-Control-Allow-Headers" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
</httpProtocol>


myComponent.component.ts:

  myService: MyService;

  constructor(myService: MyService) {
      this.myService = myService;
      this.myService.myFunction();
   }


myService.service.ts:

import { Injectable } from '@angular/core';
import { Http, Response, Request, Headers } from '@angular/http';
// import { HttpClient, HttpResponse, HttpRequest, HttpHeaders, HttpInterceptor, HttpHandler, HttpEvent } from '@angular/common/http';

import { Observable } from 'rxjs';
import { from } from 'rxjs';
import { map, filter, catchError, mergeMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})

export class MyService {
  http: Http;

  constructor(http: Http) {
    this.http = http;
  };

  public myFunction() {
    let request = new Request({
      method: "POST",
      url: "http://localhost:9090/api/values",
      withCredentials: true
    });

    return this.http.request(request)
      .pipe(map(res => res.json()))
      .subscribe(
        data => console.warn(data),
        err => console.error(err),
        () => console.log("empty")
      );
  }
}


How might I append some actual data to this service from my controller? And how might I tweak the service to use HttpClient instead? I've tried changing all the http: Http references to HttpClient, done all the HttpClient imports and commented out the .map/json portions but I still get a red line under the request argument in the line return this.http.request(request) of my service when I do so.

like image 377
Kyle Vassella Avatar asked Sep 15 '25 00:09

Kyle Vassella


2 Answers

I use this concept hope it will work out with you too.

Create property class for your Data (Match it with your class on your .net API), this also provide easy data handling Model

export class MyData
{
 username:string;
 password:string;
 isAuthenticated:boolean;
}

service

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

export class MyService {     

  constructor(private http: Http) {}

public myFunction(body:MyData) {
 let url = 'http://localhost:9090/api/values'
    return this.http.post(url,body)
      .pipe(map(res => res.json()))          
  }
}

TS

returnValue:any;
myData:MyData;
constructor(private service:MyService){
this.myData = new MyData();
}
myFunction()
{
 this.myData.username = 'anything';
 this.myData.password = 'mypw';
 this.myData.isAuthenticated = true;

 this.returnValue = this.service.myFunction(this.myData)
 .subscribe(res=>{console.log(res)})
}

.NET API

[HttpPost]
public void MYAPI([FromBody]MyData model)
{

    string uname = model.username;
    string pw = model.password;
}
like image 99
Joseph Agbing Avatar answered Sep 16 '25 12:09

Joseph Agbing


In order to use HttpClient you have to import HttpClientModule in app.module.ts instand of HttpModule and start inject HttpClient object instand of http

@Injectable({
  providedIn: 'root'
})

export class MyService {

  constructor(private http: HttpClient) {
  };

  public myFunction(body) {
    let requestOptions = { withCredentials : true };
    return this.http.post("http://localhost:9090/api/values",body,requestOptions);
  }
}

When you use HttpClient you don't need to do .map(res => res.json())

component

 constructor(myService: MyService) {
      this.myService = myService;
      this.myService.myFunction({username:'test',password:'123465'})
      .subscribe(data => console.warn(data), err => console.error(err),() => console.log("empty")
      );
   }

Normaly you don't need to subscribe from your service so you can get the data to the component

ngOnInit

As a general good practice you have to do the initial api request in ngOninit method

complete guide about http , RequestOptions

Finaly this is typescript tip

this is shorthand syntax

 constructor(private http: HttpClient) {
  };

to this

private http: HttpClient;
 constructor(http: HttpClient) {
   this.http = http
  };
like image 40
Muhammed Albarmavi Avatar answered Sep 16 '25 13:09

Muhammed Albarmavi