DEV Community

Cover image for Api Broadcasting with .NET
Dino Lozina
Dino Lozina

Posted on

Api Broadcasting with .NET

How to notify all your client apps that server content has changed?

That requirement is perhaps a standard nowadays since we have various hungry devices (and minds also ๐Ÿ˜Š) for new notifications. In this article I have tested .NET signalR since it looks like it is easy to deploy, handles connection management automatically and scales easily.

Goal is to write server-side code that can broadcast content changes to client as soon as the content changes. SignalR supports following WebSocekets, Server-Side Events and Long Pooling techniques for handling real-time communication. To communicate between clients and servers SignalR uses hubs. A hub is a high-level pipeline that allows a client and server to call methods on each other and we will write one of those methods.

On my github you will find finished project so that you do not need to write code yourself. We have Web API that knows how to do CRUD operations and client Blazor WebAssembly application that consumes data.


First Step: Define a hub โœ”๏ธ

We write a custom class, and the most important thing is to inherit from Hub class.

LiveUpdatesHub.cs

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace PublicAddressBook.Api.Hubs
{
    public class LiveUpdatesHub : Hub
    {
        public async Task LiveUpdate()
        {
            await Clients.All.SendAsync("LiveUpdate");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Note: be sure to add using statement for SignalR


Second Step: Configure our newly created class (LiveUpdatesHub) โœ”๏ธ

All the configuration for .NET 5 or Core applications is done in application Startup.cs. We will need to add endpoint over which we will broadcast data.

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
            services.AddControllers();
            services.AddDbContext<PublicAddressBookContext>(options =>
                     options.UseNpgsql(Configuration.GetConnectionString("PublicAddressBookConnection")));

            services.AddScoped<IContacts, Contacts>();

...(check github for full code ex.)

        }
Enter fullscreen mode Exit fullscreen mode

And also add service in ConfigureServicesMethod:

Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

...(check github for full code ex.)

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<LiveUpdatesHub>("/liveupdateshub");
                endpoints.MapControllers();
            });
        }
Enter fullscreen mode Exit fullscreen mode

Third Step: Notify change โœ”๏ธ

In context of this application, I want to notify or perhaps it is better to say broadcast data change. Data will change when our API receives create contact POST request. If the data is OK we will write data to DB. After that we just need to call our Hub method (โ€œLiveUpdateโ€).

ContactsController.cs

[HttpPost]
public IActionResult CreateContact([FromBody] Contact contact)
{

 ... (check github for full code ex.)

    try
    {
          var createdContact = _contactsService.AddContact(contact);
          // Live Update for Client Apps
          _hub.Clients.All.SendAsync("LiveUpdate");

          return Created("contact", createdContact);
     }
     catch (Exception ex)
     {
          log.Error("PublicAddressBookApiError: ", ex);
          return StatusCode(StatusCodes.Status500InternalServerError);
     }
}
Enter fullscreen mode Exit fullscreen mode

Note:Be sure to add hub service to controller constructor


Fourth Step: Consume changed data โœ”๏ธ

Since we stayed in .NET world it is easy to consume "data change event" or should I say listen to changes on client side.
In our Blazor component in method OnInitializedAsync() we will make a new instance of hub HubConnectionBuilder() and register what we are listening for.

ContactOverview.razor.cs

namespace PublicAddressBook.Client.Pages
{

... (check github for full code ex.)

    public partial class ContactOverview
    {

        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri(baseUrl + liveUpdateEndPoint))
            .Build();

            hubConnection.On("LiveUpdate", () =>
            {
                GetLiveNotificationData();
                StateHasChanged();
            });

            await hubConnection.StartAsync();

            await GetData();
        }

}
Enter fullscreen mode Exit fullscreen mode

Note: On client side, be sure to add SignalR client package


Conclusion ๐ŸŽ‰ ๐Ÿพ

As you can se from this example it is very easy to set up real-time updates with SignalR. On client side you are of course not limited to .NET client and on this link you can find examples for JavaScript and TypeScript. Also, I must mention that your hub method can have parameters, there is a nice chat example on fore mentioned link.

Stay well,

Dino

Discussion (0)