2

Angular makes me crazy.

I have two buttons. If I click on the first one, I want to make this request:

https://localhost:44373/api/events

If I click on the second one, I want to make that request:

https://localhost:44373/api/events/1

The method "getNextPost()" will be called and it seems to work, but on Server side the addressed Methods will not be called.

Here is my client implementation:

 export class AppComponent implements OnInit {
  title = 'EventsPresenter';
  _hubconnection : signalR.HubConnection;

  _notification : string = '';

  displayedColumns: string[] = ['eventDateTime', 'nbr', 'element', 'parent', 'stateTypeTitle', 'enumValueTitle', 'customerObject'];

  ROOT_URL = 'https://localhost:44373/';
  ROOT_API_URL = this.ROOT_URL + 'api/';
  dataSource: Observable<EventData[]>;
  dataSource2: Observable<EventData>;

  constructor(private http: HttpClient) {}

  getPosts(){
    this.dataSource = this.http.get<EventData[]>(this.ROOT_API_URL + 'events')
  }

  getNextPost(){
    this.dataSource2 = this.http.get<EventData>(this.ROOT_API_URL + 'events/1')
  }


  ngOnInit() {

    this._hubconnection = new signalR.HubConnectionBuilder() 
    .configureLogging(signalR.LogLevel.Trace) 
    .withUrl('https://localhost:44373/notify') 
   .build(); 

    this._hubconnection
      .start()
      .then(() => console.log('Connection Started'))
      .catch(err => console.log('Error while establishing connection'));

      this._hubconnection.on('BroadcastMessage', (data: EventData) => {    
        console.log(data);
        this.dataSource.subscribe(v => v.push(data));
      });

  }
}

Here is my server implementation:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using convisAPI.DataProvider;
using convisAPI.Interfaces;
using EntityLibrary;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;

namespace convisAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EventsController : ControllerBase
    {
        //EventDataProvider eventDataProvider;

        IEventDataRepository _eventDataRepository;

        IHubContext<NotifyHub> _hubContext;

        public EventsController(IEventDataRepository eventDataRepository, IHubContext<NotifyHub> hubContext)
        {
            _eventDataRepository = eventDataRepository;
            _hubContext = hubContext; 
        }

        // GET api/events
        [HttpGet]
        public async Task<ActionResult<IEnumerable<EventSummary>>> Get()
        {
            return await _eventDataRepository.GetEvents();
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public async Task<ActionResult<EventSummary>> Get(int id)
        {

            Random r = new Random();

            var ra = r.Next(212, 220);

            await _hubContext.Clients.All.SendAsync("BroadcastMessage", new EventSummary()
            {
                Element = "Mein Element " + ra,
                Details = "Das ist mein Eventgrund",
                EventID = Guid.NewGuid(),
                ElementID = Guid.NewGuid(),
                EventDateTime = DateTime.Now,
                Nbr = ra,
                StateNbr = ra,
                EnumValueTitle = "Störung",
                StateEnumValue = 110 + ra
            });


            return new EventSummary();



        }

        // POST api/values
        [HttpPost]
        public void Post([FromBody] string value)
        {
        }

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

        // DELETE api/values/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
}

I know that the code "Get(int id)" may look strange for you, but I basically want to trigger an SignalR Notification.

Any ideas?

best regards

4
  • Is your server live on another port? Commented Sep 6, 2018 at 12:45
  • Angular is running on localhost:4200 and asp.net.core on localhost:44373. Commented Sep 6, 2018 at 12:47
  • I don't know exactly what you mean.The code in getPosts() which fills datasource works. The code in getNextPost() which fills datasource2 in the exact same way does not work. Commented Sep 6, 2018 at 12:50
  • See the answer you have below. Commented Sep 6, 2018 at 12:52

3 Answers 3

6

in Angular, each HTTP request will only "fire" when someone listen´s to them.

So, if there is no one who subscribe´s, than there won´t be any http-request.

getPosts(){
    this.http.get<EventData[]>(this.ROOT_API_URL + 'events')
         .subscribe(result => this.dataSource = result)
}

getNextPost(){
    this.http.get<`EventData>(this.ROOT_API_URL + 'events/1')
        .subscribe(result => this.dataSource2 = result)
}

I would write it a bit different, but thats personal style Instead of

getPosts(){
   this.dataSource = this.http.get<EventData[]>(this.ROOT_API_URL + 'events')
 }

i would write

getPosts():Observable<EventData[]>{
   return this.http.get<EventData[]>(this.ROOT_API_URL + 'events')
}

and then i would subscribe at the point where i need the data.

...
this.getPosts().subscribe(result => this.isWhereINeedit = result)

warm regards

Sign up to request clarification or add additional context in comments.

2 Comments

ah, sorry, copy paste error. I will correct the awnser. Thank you.
Hi Jan, thank you for your answer. I also needed to change the declaration of datasource to EventData[] instead of Observable<EventData[]>
2

For those landing here that don't have any of the issues mentioned, it's worth checking your interceptors, if you have any.

Comments

1

There 2 issues here.

1st: HttpClient.get() method returns an Observable. Observable does not get triggered/fired unless they are subscribed. For Ex:

/* This wont work because it is not subscribed. */
someMethod() {
http.get(someUrl);
}

// this is work since it is subscribed.
someMethod() {
http.get(someUrl).subscribe(res => console.log(res));
}

So in your case, the call to server is not being made. Check in browser's network. If the call is made, then it should show there.

2nd: CORS ISSUE. Since the origin of Request to the server and Response from Server are different, you might be having cors issue. During the development phase, you can use a browser plugin to work around that, but it will still occure during the production (when you go live). To properly resolve it, some change needs to be made on the server side. Add these on your server:

  // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

3 Comments

Thank you for your answer. I have solved the cors issue a few days ago. You are also right with your first point. Thank you and have a nice day!
Whats to point of subscribing if i don't need to subscribe? Shouldn't there be an option fire once anyway
You can convert the request to promise with its inbuild 'toPromise' method. This way instead of Observable, you will get promise.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.