基于ASP.NET Core SignalR实现实时消息提醒与聊天功能

 更新时间:2026年01月05日 10:53:34   作者:jllllyuz  
本文主要介绍了基于ASP.NET Core SignalR实现实时消息提醒与聊天功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

基于ASP.NET Core SignalR实现实时消息提醒与聊天功能,包含服务端架构、客户端交互及关键优化点:

一、服务端实现(ASP.NET Core 7+)

1. 消息模型定义

public class ChatMessage
{
    public string SenderId { get; set; }
    public string ReceiverId { get; set; }
    public string Content { get; set; }
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    public MessageStatus Status { get; set; } = MessageStatus.Sent;
}

public enum MessageStatus
{
    Sent,
    Delivered,
    Read
}

2. SignalR Hub核心实现

using Microsoft.AspNetCore.SignalR;
using System.Collections.Concurrent;

public class ChatHub : Hub
{
    private static readonly ConcurrentDictionary<string, List<string>> _connections = 
        new ConcurrentDictionary<string, List<string>>();

    // 用户连接管理
    public override async Task OnConnectedAsync()
    {
        var userId = Context.UserIdentifier;
        if (!_connections.TryGetValue(userId, out var connections))
        {
            connections = new List<string>();
            _connections[userId] = connections;
        }
        connections.Add(Context.ConnectionId);
        
        // 通知好友在线状态
        await UpdateUserStatus(userId, true);
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        if (_connections.TryRemove(Context.UserIdentifier, out var connections))
        {
            await UpdateUserStatus(Context.UserIdentifier, false);
            connections.Remove(Context.ConnectionId);
        }
        await base.OnDisconnectedAsync(exception);
    }

    // 发送消息
    public async Task SendMessage(string receiverId, string content)
    {
        var senderId = Context.UserIdentifier;
        var message = new ChatMessage
        {
            SenderId = senderId,
            ReceiverId = receiverId,
            Content = content
        };

        // 存储消息(可选)
        await SaveMessageToDb(message);

        // 推送消息
        await Clients.Group($"user_{receiverId}").SendAsync(
            "ReceiveMessage", 
            senderId, 
            content, 
            message.Timestamp
        );

        // 标记已送达
        await Clients.Caller.SendAsync("MessageDelivered", message.Id);
    }

    // 标记已读
    public async Task MarkAsRead(int messageId)
    {
        // 更新数据库状态
        var message = await GetMessageById(messageId);
        if (message?.ReceiverId == Context.UserIdentifier)
        {
            message.Status = MessageStatus.Read;
            await SaveMessageToDb(message);

            // 通知发送者
            await Clients.Group($"user_{message.SenderId}").SendAsync("MessageRead", messageId);
        }
    }

    private static void UpdateUserStatus(string userId, bool isOnline)
    {
        // 更新全局状态缓存
        // 触发好友状态变更通知
        Clients.All.SendAsync("UserStatusChanged", userId, isOnline);
    }
}

二、客户端实现(Web前端)

1. HTML结构

<div id="chat-container">
    <div id="online-users"></div>
    <div id="message-list"></div>
    <input type="text" id="receiverId" placeholder="接收者ID">
    <input type="text" id="message-input">
    <button id="send-btn">发送</button>
</div>

2. JavaScript连接与事件处理

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect()
    .build();

// 接收消息
connection.on("ReceiveMessage", (senderId, content, timestamp) => {
    const msgElement = document.createElement("div");
    msgElement.innerHTML = `
        <strong>${senderId}</strong> (${new Date(timestamp).toLocaleTimeString()}):
        <span>${content}</span>
    `;
    document.getElementById("message-list").appendChild(msgElement);
});

// 用户状态更新
connection.on("UserStatusChanged", (userId, isOnline) => {
    const statusElement = document.getElementById(`user-${userId}-status`);
    statusElement.textContent = isOnline ? "在线" : "离线";
});

// 连接建立
connection.start().then(() => {
    console.log("已连接到SignalR服务");
}).catch(err => console.error(err.toString()));

// 发送消息
document.getElementById("send-btn").addEventListener("click", async () => {
    const receiverId = document.getElementById("receiverId").value;
    const content = document.getElementById("message-input").value;
    await connection.invoke("SendMessage", receiverId, content);
});

三、关键功能扩展

1. 消息持久化(Entity Framework Core)

public class AppDbContext : DbContext
{
    public DbSet<ChatMessage> Messages { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ChatMessage>()
            .HasIndex(m => new { m.SenderId, m.ReceiverId })
            .IsUnique(false);
    }
}

// 保存消息到数据库
public async Task SaveMessageToDb(ChatMessage message)
{
    using var dbContext = new AppDbContext();
    dbContext.Messages.Add(message);
    await dbContext.SaveChangesAsync();
}

2. 实时通知增强

// 弹窗通知(使用iziToast)
connection.on("ReceiveMessage", async (senderId, content, timestamp) => {
    iziToast.info({
        title: senderId,
        message: content,
        position: 'topRight',
        timeout: 5000
    });
});

3. 消息状态同步

// 前端标记已读
async function markMessageAsRead(messageId) {
    await connection.invoke("MarkAsRead", messageId);
}

// 接收已读确认
connection.on("MessageRead", (messageId) => {
    document.querySelector(`[data-id="${messageId}"]`).classList.add("read");
});

四、服务端配置

1. Program.cs配置

var builder = WebApplication.CreateBuilder(args);

// 添加SignalR服务
builder.Services.AddSignalR(hubOptions => {
    hubOptions.EnableDetailedErrors = true;
    hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(2);
});

// 添加身份认证(JWT示例)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => {
        options.TokenValidationParameters = new TokenValidationParameters {
            ValidateIssuer = true,
            ValidateAudience = true
        };
    });

var app = builder.Build();

// 路由配置
app.UseAuthentication();
app.UseAuthorization();
app.MapHub<ChatHub>("/chathub");
app.Run();

参考代码 使用SignalR实现消息提醒(聊天源码) www.youwenfan.com/contentcso/92650.html

五、性能优化方案

  1. 连接管理 使用ConcurrentDictionary维护用户连接池 实现连接心跳检测机制

  2. 消息分片

    // 大文件分片传输
    public async Task SendLargeFile(IFormFile file)
    {
        var buffer = new byte[4096];
        using (var stream = file.OpenReadStream())
        {
            int bytesRead;
            while ((bytesRead = await stream.ReadAsync(buffer)) > 0)
            {
                await Clients.Caller.SendAsync("ReceiveFileChunk", 
                    file.Name, buffer, bytesRead);
            }
        }
    }
    
  3. 负载均衡

    • 配置Redis作为SignalR后端存储
    builder.Services.AddSignalR().AddStackExchangeRedis("redis_connection_string");
    

到此这篇关于基于ASP.NET Core SignalR实现实时消息提醒与聊天功能的文章就介绍到这了,更多相关ASP.NET Core SignalR实时内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Asp.net中的数据绑定Eval和Bind应用示例

    Asp.net中的数据绑定Eval和Bind应用示例

    这篇文章主要介绍了Asp.net中的数据绑定Eval和Bind的应用,需要的朋友可以参考下
    2014-05-05
  • log4net教程日志分类和自动维护示例

    log4net教程日志分类和自动维护示例

    log4net能不能按照功能分类呢?如果通过配置不同的logger,然后功能根据不同的LoggerName加载Ilog实例,是可以做到。但由于这些功能的log配置差异性极小,也许仅仅就是文件名不同。于是想通过代码进行配置,下面把方法分享如下
    2014-01-01
  • 用javascript打造搜索工具栏

    用javascript打造搜索工具栏

    用javascript打造搜索工具栏...
    2006-09-09
  • ASP.NET中实现把Json数据转换为ADO.NET DataSet对象

    ASP.NET中实现把Json数据转换为ADO.NET DataSet对象

    这篇文章主要介绍了ASP.NET中实现把Json数据转换为ADO.NET DataSet对象,本文讲解设计及实现方法,相关代码托管到GITHUB,需要的朋友可以参考下
    2015-03-03
  • .Net Core实现第三方QQ扫码登录

    .Net Core实现第三方QQ扫码登录

    这篇文章介绍了.Net Core实现第三方QQ扫码登录的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • .Net WebApi消息拦截器之MessageHandler的示例

    .Net WebApi消息拦截器之MessageHandler的示例

    这篇文章主要介绍了.Net WebApi消息拦截器之MessageHandler的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 使用Seq搭建免费的日志服务的方法

    使用Seq搭建免费的日志服务的方法

    这篇文章主要介绍了使用Seq搭建免费的日志服务的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • .NET中的HashSet及原理解析

    .NET中的HashSet及原理解析

    HashSet定义在System.Collections.Generic中,是一个不重复、无序的泛型集合,本文学习下HashSet的工作原理,对.NET中的HashSet相关知识感兴趣的朋友一起看看吧
    2022-03-03
  • ASP.NET Core对Controller进行单元测试的完整步骤

    ASP.NET Core对Controller进行单元测试的完整步骤

    这篇文章主要给大家介绍了关于ASP.NET Core对Controller进行单元测试的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用ASP.NET Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-06-06
  • 关于.NET Attribute在数据校验中的应用教程

    关于.NET Attribute在数据校验中的应用教程

    这篇文章主要给大家介绍了关于.NET Attribute在数据校验中的应用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用.NET具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-05-05

最新评论