How to send message from the js library to a group in Azure SignalR Serverless - signalr

Hi I'm trying to send a message to a group using the Azure Signal R Serverless JS Client Js Library.
I can do this from the Azure Serverless Function as simply as:
await signalRMessages.AddAsync(
new SignalRMessage
{
GroupName = m.GroupName,
Target = m.Target,
Arguments = new[] { m.Message }
});
*where signalRMessages = IAsyncCollector signalRMessages
How can I send this same message from the js library?

trying to send a message to a group using the Azure Signal R Serverless
You can refer to this github repo that shows with sample code how to implement group broadcasting functionality in Azure functions with Azure SignalR Service.
Add user to a group using the SignalRGroupAction class
return signalRGroupActions.AddAsync(
new SignalRGroupAction
{
ConnectionId = decodedfConnectionId,
UserId = message.Recipient,
GroupName = message.Groupname,
Action = GroupAction.Add
});
On client side, make request to endpoint to add a user to a group
function addGroup(sender, recipient, connectionId, groupName) {
return axios.post(`${apiBaseUrl}/api/addToGroup`, {
connectionId: connectionId,
recipient: recipient,
groupname: groupName
}, getAxiosConfig()).then(resp => {
if (resp.status == 200) {
confirm("Add Successfully")
}
});
}
Test Result
Updated:
Q: "send the message from the JS Client straight from the socket".
A: From here, we can find:
Although the SignalR SDK allows client applications to invoke backend logic in a SignalR hub, this functionality is not yet supported when you use SignalR Service with Azure Functions. Use HTTP requests to invoke Azure Functions.

It's seems like this is now possible ...
https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-concept-serverless-development-config#sending-messages-from-a-client-to-the-service
Sending messages from a client to the service If you have upstream
configured for your SignalR resource, you can send messages from
client to your Azure Functions using any SignalR client. Here is an
example in JavaScript:
JavaScript
connection.send('method1', 'arg1', 'arg2');

Related

Custom Headers with GRPC in .NET Core

I am working on building a service in GRPC using .NET core. The scenario is as follows - there are 2 services - A and B.
Service A exposes a REST API.
Service B exposes GRPC API.
User invokes Service A, and Service A invokes Service B. I need to pass the headers sent by the user to Service B.
How can I do this with GRPC? The Interceptor interface does not seem to expose the Metadata collection.
To forward the headers sent from client, on the rest api you can do something like this:
using var channel = GrpcChannel.ForAddress("http://localhost:5005");
var client = new Greeter.GreeterClient(channel);
Metadata headers = new()
{
{ "myCustomHeader", myCustomHeader }
};
var reply = await client.SayHelloAsync(new HelloRequest { Name = model.Name }, headers);
Using the Metadata you can pass all headers that you need.
On the gRPC service side, you need to use HttpContextAccessor here
This way you can read the http context request headers
string header = _httpContextAccessor.HttpContext.Request.Headers["myCustomHeader"];
take a look at this repo: here

Azure SignalR Notifications from Service Bus Qeue

We have a Service Bus queue that handles multiple message topics/subscriptions and what we'd like to be able to do is when certain messages have been handled is to notify connected users that a message has been handled.
The message handling takes place in a simple console app but we're not sure how to create a connection to our Azure SignalR service and send a message once it's been processed.
I believe the simplest most scalable approach would be to have a simple azure function to do this.
You would just have to use the Service Bus Trigger which runs your function when a message arrives and use the SignalR Service Output Binding to send the message to your users.
Your function could be as simple as the following
[FunctionName("ServiceBusQueueTriggerCSharp")]
public static void Run(
[ServiceBusTrigger("myqueue", AccessRights.Manage, Connection = "ServiceBusConnection")]
string myQueueItem,
[SignalR(HubName = "chat")]IAsyncCollector<SignalRMessage> signalRMessages
ILogger log)
{
return signalRMessages.AddAsync(
new SignalRMessage
{
Target = "newMessage",
Arguments = new [] { myQueueItem }
});
}

ASP.NET 5 SignalR not working with .NET client

I work on a ASP.NET 5 (ASP.NET vNext) website. I use SignalR server (1.0 Beta 3) for some processing. It it is correctly set up because I can successfully invoke server methods from a Javascript browser client.
But when a I use .NET client (.NET 4.5 with SignalR 2.2.0), the method invoke fail with the generic "error 500".
I have downloaded both SignalR server and client sources to be able to debug them. I have seen that DefaultHttpClient.Post() client method is called with valid "postData" parameter, but the server PersistentConnectionMiddleware.Invoke() method has a http context without any "Form" value inside the request. And it makes SignalR server side failing in the ForeverTransport.ProcessSendRequest() method.
The post form seems to be forgotten during the transfer between the client and the server (I use the default IIS Express server).
Any idea? Thank you...
I saw the issue you opened and have committed a fix/workaround.
At the moment it doesn't look like SignalR 3 works with the client due to the fact it expects all requests to be form encoded. The workaround is to update ProcessSendRequest() so it can get the non-form-encoded data from the 2.2 .NET client;
protected virtual async Task ProcessSendRequest()
{
var data = await GetData().PreserveCulture();
if (Received != null)
{
await Received(data).PreserveCulture();
}
}
private async Task<string> GetData()
{
if (Context.Request.HasFormContentType)
{
var form = await Context.Request.ReadFormAsync().PreserveCulture();
return form["data"];
}
else
{
var stream = new System.IO.StreamReader(Context.Request.Body);
var output = await stream.ReadToEndAsync().PreserveCulture();
var decoded = UrlDecoder.UrlDecode(output);
return decoded.Replace("data=", "");
}
}

Using SignalR to send message to client from Azure Worker Role

I'm working an ASP.net MVC cloud service project running two roles, a web role and a worker role. One of the pages in the web role initiate a request to build an APK file, building an APK file on the server can take anywhere from 1-5 minutes. So we came up with the following flow:
The user initiate the APK building process on the page.
The request is routed to our mvc action, creating a new message on an Azure Storage Queue.
The Worker role is always polling from the queue and starts the APK building process. Now that the APK is ready we want ideally to notify the user by:
(a) sending an email, which is working now. and (b) notifying the user on the page using SignalR.
Our problem is now in the SignalR part, how can we notify the user on the page that the APK is ready and he can download it.
EDIT - Copying contents of the first comment for the sake of completeness -
I've looked the question again and I understand that you are using a worker role to poll the queue. In this case, you can make your work role a .Net SignalR client that connects to the APK signalR hub on the web role. The signlaR hub on the web role can simple forward any message it receives from the .Net client to the javascript client (browser).
I would recommend going through the below links
Hubs API Guide - Server
Hubs API Guide - Javascript Client
before going through rest of the answer.
As can be understood from the above two links, SignalR enables the server to 'push' data to the client. In order for this to happen, you require two things -
A signalR hub - this is the 'hub' to which clients can subscribe to in order to receive messages.
A client connected to the hub
Your signalR hub on the server can look something like this -
public class APKHub : Hub
{
public async Task JoinGroup(string groupName)
{
await Groups.Add(Context.ConnectionId, groupName);
Clients.Group(groupName).sendMessage(Context.User.Identity.Name + " joined.");
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
public void NotifyUser(string userId)
{
this.Clients.Group(userId).notify();
}
}
On the client, your code might look something like this -
var notificationHandler = function () {
var url;
var user;
var init = function (notificationUrl, userId) {
url = notificationUrl;
user = userId;
connectToAPKHub();
}
var connectToAPKHub = function () {
$.connection.hub.url = url;
var apk= $.connection.apkHub;
apk.client.notifyUser = function (user) {
console.log(user);
}
apk.client.addMessage = function (message) {
console.log(message);
}
$.connection.hub.start().done(function () {
console.log('connected to apkhub');
apk.server.joinGroup(user);
})
}
return {
init: init
}
}();
The notificationUrl is the URL that the signalR server is listening to.
This sets up your basic hub on the server and you should now be able to connect your client to the signalR hub. When the APK is built, you can use the following code (place it anywhere - for ex - in a controller action) to actually push a message to the concerned client -
var apkHub = GlobalHost.ConnectionManager.GetHubContext<APKHub>();
apkHub.Clients.Group(groupName).notifyUser(groupName);
The groupName can be an identifier that uniquely identifies a user.
Hope this helps.

Use Signalr to have a facebook like notification system

I want to implement a facebook like notification system in ASP.NET MVC 3 : notifications are sent to a specific user to notify him for an action on one of his items.
Is signalr suited for such requirement?
How could i send a notification to a specific user (all opened sessions of this user) using SignalR?
Edit
Ok, Here what i did
In the client side
$(function () {
// Proxy created on the fly
var chat = $.connection.chat;
var username = '#Html.ViewContext.HttpContext.User.Identity.Name';
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) {
$('#messages').append('<li>' + message + '</li>');
};
// Start the connection
$.connection.hub.start(function (){
chat.join(username);
});
});
In the server side
public class Chat : Hub
{
public void Join(string username)
{
AddToGroup(username);
}
}
And every time i need to notify a user in the controller i do the following:
IConnectionManager connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
dynamic clients = connectionManager.GetClients<Chat>();
clients[username].addMessage("test");
Yes, SignalR is a good choice for that. Take a look at the documentation regarding Hubs (server and JS client).
You need to implement the server logic to associate your client's session with SignalR's session. You can use groups to notify all the open sessions of each user.
It is appropriate for this or you use polling, those are the two choices.
Heres a brand new video from today on this:
http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR?utm_source=dlvr.it&utm_medium=twitter

Resources