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
.
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace RadzenBlazorSignalR.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string message)
{
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
}
In Program.cs, map the endpoint for the Blazor hub:
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.
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.
public async Task Send()
{
if (hubConnection is not null)
{
await hubConnection.SendAsync("SendMessage", _messageToSend);
}
}
Below the complete Blazor's page backend code.
public partial class HomeComponent
{
[Inject]
protected NavigationManager MyUriHelper { get; set; }
public string _messageToSend { get; set; }
public string _messageRecived { get; set; }
private HubConnection hubConnection;
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(MyUriHelper.ToAbsoluteUri("/chathub"))
.Build();
hubConnection.On<string>("ReceiveMessage", (message) =>
{
_messageRecived = message;
StateHasChanged();
});
await hubConnection.StartAsync();
}
public async Task Send()
{
if (hubConnection is not null)
{
await hubConnection.SendAsync("SendMessage", _messageToSend);
}
}
}
@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.
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.
async Task InviaAsync()
{
if (hubConnection != null)
{
await hubConnection.SendAsync("SendMessage", "Desktop: Ciao");
}
}
Below is the complete code:
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