Reputation: 199
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
Upvotes: 2
Views: 6597
Reputation: 1040
For those landing here that don't have any of the issues mentioned, it's worth checking your interceptors, if you have any.
Upvotes: 2
Reputation: 1847
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
Upvotes: 6
Reputation: 2508
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);
Upvotes: 1