DEV Community

Cover image for SignalR - ChatApp | .NET 6
Nosirbek
Nosirbek

Posted on • Edited on

4 3

SignalR - ChatApp | .NET 6

Yangi Blazor Server Project ochamiz.
Image description

dotnet new blazorserver -o ChatApp
Enter fullscreen mode Exit fullscreen mode

1- qadam : Loyihaga SignalR package ni qo'shamiz.

Microsoft.AspNetCore.SignalR.Client
Enter fullscreen mode Exit fullscreen mode

2- qadam : Hubs nomli Folder yaratib ichiga ChatHub.cs file ochamiz .

Hubs/ChatHub.cs

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ChatApp.Hubs;
public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}
Enter fullscreen mode Exit fullscreen mode

3- qadam : Program.cs da ro'yxatdan o'tkazamiz.

Image description

using ChatApp.Data;
using ChatApp.Hubs;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.ResponseCompression;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

builder.Services.AddResponseCompression(opts => {
    opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "application/octet-stream" });
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();

app.MapHub<ChatHub>("/chathub");

app.MapFallbackToPage("/_Host");

app.Run();
Enter fullscreen mode Exit fullscreen mode

4- qadam : Models Folder yaratib uni ichida UserMessage.cs ochamiz.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ChatApp.Models;
public class UserMessage
{
    public string Username { get; set; }
    public string Message { get; set; }
    public bool CurrentUser { get; set; }
    public DateTime DateSent { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

5- qadam : Pages/Index.razor ning ichidagilarni ochirib tashlaymiz va quyidagilarni yozamiz .

@page "/"
@using Microsoft.AspNetCore.SignalR.Client
@using Models
@inject NavigationManager NavigationManager
@implements IAsyncDisposable

<div class="container overflow-auto shadow-sm p-3 mb-5 bg-white rounded" style="height: 500px;">
    @if (!userMessages.Any())
    {
        <p>No messages yet, start chatting!</p>
    }

    @foreach (var userMessage in userMessages)
    {
        <div class="row mb-3 d-flex @(userMessage.CurrentUser ? "justify-content-end" : "")">
            <div class="card shadow @(userMessage.CurrentUser ? "p-3 mb-2 bg-primary text-white" : "ml-5")" style="width: 18rem;">
                <div class="card-header">
                    @(userMessage.CurrentUser ? "You" : userMessage.Username)
                </div>
                <ul class="list-group list-group-flush">
                    <li class="list-group-item @(userMessage.CurrentUser ? "p-3 mb-2 bg-primary text-white" : "")">@userMessage.Message</li>
                </ul>
                <div class="card-footer">
                    <span class="small">@userMessage.DateSent.ToString("HH:mm | MMM dd")</span>
                </div>
            </div>
        </div>
    }
</div>

<div class="container">
    <div class="row">
        <div class="col-3">
            <input @bind="usernameInput" type="text" class="form-control" placeholder="Your name" readonly="@isUserReadonly"/>
        </div>
        <div class="col-6">
            <textarea @bind="messageInput" class="form-control" placeholder="Start typing..."></textarea>
        </div>
        <div class="col-3">
            <button type="button" @onclick="Send" disabled="@(!IsConnected)" class="btn btn-primary">Send</button>
        </div>
    </div>
</div>

@code{
    private HubConnection hubConnection;
    private List<UserMessage> userMessages = new();
    private string usernameInput;
    private string messageInput;
    private bool isUserReadonly = false;

    public bool IsConnected => hubConnection.State == HubConnectionState.Connected;

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

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            userMessages.Add(new UserMessage { Username = user, Message = message, CurrentUser = user == usernameInput, DateSent = DateTime.Now });

            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    private async Task Send()
    {
        if (!string.IsNullOrEmpty(usernameInput) && !string.IsNullOrEmpty(messageInput))
        {
            await hubConnection.SendAsync("SendMessage", usernameInput, messageInput);

            isUserReadonly = true;
            messageInput = string.Empty;
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (hubConnection is not null)
        {
            await hubConnection.DisposeAsync();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Image description

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up