Creating a cross-platform chat app using Xamarin Forms and SignalR
In less than 5 minutes.
First step is to create your Xamarin Forms projects – start with a blank shell app – and add an additional blank ASP.NET Core project to the solution – we will use it to host our SignalR backend.
Once the projects are setup, we begin by implementing the ChatHub
which in our case is really basic.
public class ChatHub : Hub
{
public async Task Send(string from, string message)
{
await Clients.Others.SendAsync("broadcastMessage", from, message);
}
}
Code language: C# (cs)
This is our SignalR chat hub to which our Xamarin client apps will connect. It only has one method – Send
– which accepts two parameters: the name of the user sending the message (from) and the actual message. This will then call the “broadcastMessage” method on all the connected clients except the sender (we don’t want the message we send to be sent back to us).
All that’s left to do is to register SignalR and the ChatHub and we’re done with the backend part. To do so, open up Startup.cs
and inside the ConfigureServices
method add the following line:
services.AddSignalR();
Code language: C# (cs)
And inside the Configure
method add and endpoint mapping for your hub. You already have a default mapping in there, so just add it next to it. This is how it should look:
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
endpoints.MapHub<ChatHub>("/chat");
});
Code language: C# (cs)
Build and run the web project, if everything is ok, you will see “Hello World!” in your browser window.
The Xamarin client
On the client side we want something simple:
- a Connect button
- a list with chat messages
- a textbox where you can type your own message
- a Send button
Note: you might argue that we don’t need a Connect button, and that’s true in most cases, but when you debug all projects at once, you can’t automatically connect to the hub, because most of the time the web app hasn’t finished warming up by the time the app initializes and you will end up with a connection error.
The main flow that we want to achieve:
- when launching the application we only want the Connect button and the list of messages to be visible
- after connecting to the hub, we want the Connect button to disappear and to display the message
Entry
and the Send button - pressing Connect will connect to the chat hub
- upon receiving a message we will display it on the UI
- sending a message will send it to the hub and also add it to the messages list on the UI
- in case of any error we display it as a message
Feel free to create the UI as you like, here’s my version of it:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SignalRChat.MainPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Messages}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding From}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding Content}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Command="{Binding ConnectCommand}" IsVisible="{Binding IsConnected, Converter={StaticResource BooleanToOppositeBooleanConverter}}" Grid.Row="1" Text="Connect" />
<Grid IsVisible="{Binding IsConnected}" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Entry Text="{Binding Message, Mode=TwoWay}" />
<Button Command="{Binding SendCommand}" Grid.Column="1" Text="SEND" TextColor="White" Background="#0069c0" />
</Grid>
</Grid>
</ContentPage>
Code language: HTML, XML (xml)
If something doesn’t work, you can check out a working sample here: Xamarin Forms – SignalR Chat, or you can reach out in the comments below.