Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Blazor Communicates with Win Desktop App through SignalR

5.00/5 (11 votes)
17 Mar 2022CPOL2 min read 9.2K  
Blazor and Windows Form desktop application
In this tip, you will learn how to resolve a communication problem between an old Windows Form application and a Blazor web based app.

Introduction

I had to find a solution to resolve a communication problem between an old Windows Form application and a Blazor web based app.

You may be wondering, why a Windows Form should communicate with Blazor? The scenario is: I have an old Framework 2.0 application, then it migrates to Framework 4.8, installed on the client that uses Windows API but that needs to exchange data with a Blazor app.

Background

ASP.NET Core SignalR is very simple to implement in Blazor App and the communication is extremely rapid. I suggest you read the Microsoft tutorial to understand the functionalities.

Blazor Code

Note: Below, I have the same Microsoft tutorial step, then if you have already made the tutorial, you can use it.

First of all, we need Visual Studio 2022 and create a Blazor server app .NET 6.0. Inside the app, create a folder called Hubs and then a class called ChatHub.

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

namespace RadzenBlazorSignalR.Hubs
{
    public class ChatHub : Hub //NB: inherits from Hub
    {
        public async Task SendMessage(string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", message);
        }
    }
}

In Program.cs, map the endpoint for the Blazor hub:

C#
app.UseEndpoints(endpoints =>
           {
               endpoints.MapHub<ChatHub>("/chathub");
           });

Now the Hub is ready but the application needs to send and receive some messages, so we need to implement the clients side.

To do this, first add Microsoft.AspNetCore.SignalR.Client package and then create a method to initialize the connection.

C#
HubConnection hubConnection;
string _messageRecived { get; set; }

protected override async Task OnInitializedAsync()
{
     hubConnection = new HubConnectionBuilder()
       .WithUrl(MyUriHelper.ToAbsoluteUri("/chathub"))
       .Build();
            
     hubConnection.On<string>("ReceiveMessage", (message) =>
     {
        _messageRecived = message;
        StateHasChanged();
     });

     await hubConnection.StartAsync();
}

In the code above, I've used a Blazor's back end code OnInitializedAsync() that fired when a Blazor page is started.

HubConnectionBuilder() builds the local Blazor app Uri from ToAbsoluteUri() and Hub's name chathub.

hubConnection.On<> maps the ReceiveMessage event, fired when a SendMessage() method is called.

Now prepare a method to send a message, that you can call from a Blazor page button.

C#
public async Task Send()
{
    if (hubConnection is not null)
    {
        await hubConnection.SendAsync("SendMessage", _messageToSend);
    }
}

Below the complete Blazor's page backend code.

C#
public partial class HomeComponent
{
    [Inject]
    protected NavigationManager MyUriHelper { get; set; }//to get current Uri
    public string _messageToSend { get; set; }//to bind on textbox
    public string _messageRecived { get; set; }//to bind on a label or so...

    private HubConnection hubConnection;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
        .WithUrl(MyUriHelper.ToAbsoluteUri("/chathub"))
        .Build();

        //receive event
        hubConnection.On<string>("ReceiveMessage", (message) =>
        {
            _messageRecived = message;
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    //send message
    //call Send method from button click
    public async Task Send()
    {
        if (hubConnection is not null)
        {
            await hubConnection.SendAsync("SendMessage", _messageToSend);
        }
    }
}
Razor
@page "/"
@page "/home"
@layout MainLayout
@inherits RadzenBlazorSignalR.Pages.HomeComponent

@using Radzen
@using Radzen.Blazor
<PageTitle>Home</PageTitle>
<RadzenContent Container="main">
  <ChildContent>
    <RadzenHeading Size="H1" Text="Home">
    </RadzenHeading>
    <div class="row">
      <div class="col-md-3">
        <RadzenTextBox @bind-Value="@(_messageToSend)" Name="Textbox0">
        </RadzenTextBox>
      </div>
      <div class="col-md-3">
        <RadzenButton Text="Invia" Click="@Button0Click">
        </RadzenButton>
      </div>
      <div class="col-md-4">
        <RadzenLabel Text="@($"{(_messageRecived)}")">
        </RadzenLabel>
      </div>
    </div>
  </ChildContent>
</RadzenContent>

Note: I've used the Radzen components in the Razor page. If you are interested, look here.

Now test the app, when the app starts, copy url in another browser and, if all is right, when you send a message from an app, you will see on the other and vice versa.

Windows Form Code

Now we build a Windows form app used by the client to send and receive messages from a local Blazor app.

Open Visual Studio and create a new Windows Form framework 4.8 app.

From NuGet, install the Microsoft.AspNetCore.SignalR.Client package, that contains the client for ASP.NET Core SignalR.

We need to do the same Blazor's client implementation, so create the initialized method and call it from load form.

C#
async Task InizializzaConnectioTuBlazorHub()
{
    hubConnection = new HubConnectionBuilder()
   .WithUrl("http://localhost:5000/chathub")
   .Build();

    hubConnection.On<string>("ReceiveMessage", (message) =>
    {
        _messageRecived = message;
        textBox1.Text= _messageRecived;
    });

    await hubConnection.StartAsync();
}

Note the local app Url "http://localhost:5000/chathub".

Prepare the Send method and call it from a click button event.

C#
async Task InviaAsync()
{
    if (hubConnection != null)
    {
        await hubConnection.SendAsync("SendMessage", "Desktop: Ciao");
    }
}

Below is the complete code:

C#
private void Form1_Load(object sender, EventArgs e)
{
    InizializzaConnectioTuBlazorHub();
}

private void button1_Click(object sender, EventArgs e)
{
    Send();
}

HubConnection hubConnection;
string _messageRecived;

async Task InizializzaConnectioTuBlazorHub()
{
    hubConnection = new HubConnectionBuilder()
   .WithUrl("http://localhost:5000/chathub")
   .Build();

    hubConnection.On<string>("ReceiveMessage", (message) =>
    {
        _messageRecived = message;
        textBox1.Text= _messageRecived;
    });

    await hubConnection.StartAsync();
}

async Task Send()
{
    if (hubConnection != null)
    {
        await hubConnection.SendAsync("SendMessage", "Desktop: Bye!");
    }
}

That's all!

If you start the Blazor app and the Windows app, you can send and receive messages from all apps.

Conclusion

In this example, we have seen how it's easy to communicate with SignalR, not only between Blazor app but also with Windows desktop application.

References

History

  • 17th March, 2022: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)