user6680
user6680

Reputation: 139

SignalR Message not sending - Angular

I'm trying to send a message using SignalR and Angular, but the API never gets hit on the backend. No status code at all so it never makes it to API endpoint. The hub connection establishes fine so I would think it hits the endpoint automatically when executing this.hubConnection.invoke('NewMessage', message); but it doesn't seem to work. I'm really new to SignalR so I appreciate any help!

messaging azure function code

module.exports = async function (context, req) {
  return {
    "target": "newMessage",
    "arguments": [ req.body ]
  };
};

function.json

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "signalR",
      "name": "$return",
      "hubName": "chat",
      "direction": "out"
    }
  ]
}

angular service

import { Injectable, EventEmitter } from "@angular/core";
import * as signalR from "@aspnet/signalr";
import { SignalViewModel } from "./signal-view-model";

@Injectable({
  providedIn: "root"
})
export class SignalRService {
  private hubConnection: signalR.HubConnection;
  signalReceived = new EventEmitter<SignalViewModel>();

  constructor() {
    this.buildConnection();
    this.startConnection();
  }

  private buildConnection = () => {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:7070/api")
      .build();
  };
  sendMessage(message: SignalViewModel) {
    this.hubConnection.invoke('NewMessage', message);
  }
  private startConnection = () => {
    this.hubConnection
      .start()
      .then(() => {
        console.log("Connection Started...");
        this.registerSignalEvents();
      })
      .catch(err => {
        console.log("Error while starting connection: " + err);

        //if you get error try to start connection again after 3 seconds.
        setTimeout(function () {
          this.startConnection();
        }, 3000);
      });
  }

  private registerSignalEvents() {
    this.hubConnection.on("SignalMessageReceived", (data: SignalViewModel) => {
      this.signalReceived.emit(data);
    });
  }
}

angular component

 txtMessage: string = 'd';
  uniqueID: string = new Date().getTime().toString();
  messages = new Array<SignalViewModel>();
  signalRMessage = new SignalViewModel();
  sendMessage(): void {
    if (this.txtMessage) {
      console.log("Executing signalr")
      this.signalRMessage = new SignalViewModel();
      this.signalRMessage.clientuniqueid = this.uniqueID;
      this.signalRMessage.type = "sent";
      this.signalRMessage.message = this.txtMessage;
      this.signalRMessage.date = new Date();
      this.messages.push(this.signalRMessage);
      this.signalRService.sendMessage(this.signalRMessage);
      this.txtMessage = '';
    }

negotiate function


module.exports = async function (context, req, connectionInfo) {
  context.res.json(connectionInfo);
};

function.json of negotiate function

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "signalRConnectionInfo",
      "name": "connectionInfo",
      "hubName": "chat",
      "direction": "in"
    }
  ]
}

Upvotes: 1

Views: 1561

Answers (1)

Kiril1512
Kiril1512

Reputation: 3621

The problem is that you have the "NewMessage" with the capital "N" on the client side and "newMessage" on the function.

module.exports = async function (context, req) {
  return {
    "target": "newMessage", // "n"
    "arguments": [ req.body ]
  };
};
 sendMessage(message: SignalViewModel) {
    this.hubConnection.invoke('NewMessage', message); // "N"
  }

Also take a look at this documentation about Azure SignalR Service in Serverless mode. As you can see, if your hub is configured to Serverless mode, you can't call methods from client.

If you're using Azure SignalR Service in Serverless mode, you cannot call hub methods from a client. For more information, see the SignalR Service documentation. Link

Update: Since you are working on Azure Functions and you need to run SignalR on serverless mode, as you can see below you can't invoke hub methods from the client.

Upvotes: 1

Related Questions