1

So I was following several tutorials here: https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-azure-functions-csharp and https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-concept-serverless-development-config

My problem is that all the examples show a CRON operation or just an in scope console log broadcast. But what I want an UPDATE to a collection to trigger a broadcast?

In a Web App I could do something like this. And this worked FINE when testing with multiple clients.

[HttpPost]
public async Task<IActionResult> Insert([FromQuery] string firstName, string lastName)
{
     await _repo.InsertNewPerson(firstName, lastName);
     //This hub essentially has almost nothing set up except: 
     // endpoints.MapHub<ContactsHub>("/contacts");  setup in startup
     await _hub.Clients.All.SendAsync("transfercontactdata", _repo.GetContacts());
     return StatusCode(201);
}

However in an Azure Function with doing Microsoft's canned class of adding a 'Broadcast' [SignalRTrigger] I see this

public class SignalRTestHub : ServerlessHub
{
    private IContactsRepo _repo = new ContactsRepo();

    [FunctionName("negotiate")]
    public SignalRConnectionInfo Negotiate([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req, [SignalRConnectionInfo(HubName = "SignalRTestHub")] SignalRConnectionInfo connectionInfo)
    {
        return connectionInfo;
    }

    //Brett: Do I need this arg more in other events to ensure this acts as a load balancer??? ... ran out of time, [SignalRConnectionInfo(HubName = "SignalRTestHub")] SignalRConnectionInfo connectionInfo
    [FunctionName(nameof(OnConnected))]
    public async Task OnConnected([SignalRTrigger] InvocationContext invocationContext, ILogger logger, [SignalRConnectionInfo(HubName = "SignalRTestHub")] SignalRConnectionInfo connectionInfo)
    {
        //await Clients.All.SendAsync(NewConnectionTarget, new NewConnection(invocationContext.ConnectionId));
        logger.LogInformation($"{invocationContext.ConnectionId} has connected");
    }

    [FunctionName(nameof(Broadcast))]
    public async Task Broadcast([SignalRTrigger] InvocationContext invocationContext, string message, ILogger logger)
    {
        //Broadcast on update the same as the get call on the other function
        await Clients.All.SendAsync("getting data", await _repo.GetContacts());
        logger.LogInformation($"{invocationContext.ConnectionId} broadcast {message}");
    }

    [FunctionName(nameof(OnDisconnected))]
    public void OnDisconnected([SignalRTrigger] InvocationContext invocationContext)
    {
    }
    
}

Then I have another Function of HTTP triggers like this:

public static class SignalRTesting
{
    private static IContactsRepo _repo  = new ContactsRepo();
    private static SignalRTestHub _hub = new SignalRTestHub();
    private static SignalRConnectionInfo _info;

    static SignalRTesting()
    {
        //Not sure how connect or need to
        _info = _hub.Negotiate(null, null);
    }

    [FunctionName("GetData")]
    public static async Task<IActionResult> GetData([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log) => new OkObjectResult(await _repo.GetContacts());

    [FunctionName("UpdateData")]
    public static async Task<IActionResult> UpdateData([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, ILogger log)
    {
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        var data = JsonConvert.DeserializeObject<Contact>(requestBody);
        await _repo.InsertNewPerson(data.FirstName, data.LastName);
        await _hub.Broadcast()  //I need a context from above I am guessing

        return new NoContentResult();
    }
}

So my question is how do you get an HTTP POST or PUT request to call the broadcast with the functions? It seems to me that a hub broadcast needs a connection so almost like there was a service side acting like a client but I'm not sure.

djangojazz
  • 14,131
  • 10
  • 56
  • 94

1 Answers1

-2

In Azure Functions, you just must leverage the SignalR Service Output Binding to broadcast to all clients. The rest is taken care of by the underlying libraries.

PramodValavala
  • 6,026
  • 1
  • 11
  • 30