如何用ASP.NET MVC和SignalR实现可实时更新的项列表?
嘿,你已经把基础的架子搭得差不多了!接下来咱们一步步把实时同步的增删功能落地,分后端和前端两部分来实现:
一、完善后端的SignalR Hub与数据管理
首先,咱们得给ItemHub添加核心方法,还要解决数据共享的问题——因为SignalR的Hub实例是每次请求都会创建的,所以得用一个静态集合来保存所有Item,确保所有连接的客户端都能看到同一份数据:
using System.Collections.Generic; using System.Linq; using Microsoft.AspNet.SignalR; public class ItemHub : Hub { // 用静态集合存储Item,保证所有Hub实例共享这份数据 private static readonly ItemList _sharedItemList = new ItemList { Items = new List<Item>() }; // 供客户端获取当前所有Item的方法 public List<Item> GetCurrentItems() { return _sharedItemList.Items; } // 添加Item的方法,执行完通知所有客户端更新 public void AddItem(string itemName) { if (!string.IsNullOrWhiteSpace(itemName)) { var newItem = new Item { Name = itemName }; _sharedItemList.Items.Add(newItem); // 给所有连接的客户端发送更新通知,传递最新的Item列表 Clients.All.ItemsUpdated(_sharedItemList.Items); } } // 删除Item的方法,执行完通知所有客户端更新 public void DeleteItem(string itemName) { var targetItem = _sharedItemList.Items.FirstOrDefault(i => i.Name.Equals(itemName, System.StringComparison.OrdinalIgnoreCase)); if (targetItem != null) { _sharedItemList.Items.Remove(targetItem); // 通知所有客户端刷新列表 Clients.All.ItemsUpdated(_sharedItemList.Items); } } }
二、配置SignalR路由
接下来要让ASP.NET知道SignalR的路由,如果你用的是带Owin的Startup类,就在Startup.cs里添加SignalR的映射:
using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(YourAppName.Startup))] namespace YourAppName { public class Startup { public void Configuration(IAppBuilder app) { // 配置SignalR路由 app.MapSignalR(); // 保留你原本的MVC配置代码... } } }
如果是旧版的MVC(用Global.asax),就在Application_Start方法里加一行:
RouteTable.Routes.MapHubs();
三、完善前端Items.cshtml视图
现在轮到前端了,咱们要引入SignalR的脚本,写页面结构,再实现和Hub的交互逻辑:
首先,在视图里引入必要的脚本(注意顺序:先jQuery,再SignalR核心,最后自动生成的Hub代理):
<script src="~/Scripts/jquery-3.6.0.min.js"></script> <script src="~/Scripts/jquery.signalR-2.4.3.min.js"></script> <!-- 这个是SignalR自动生成的Hub代理脚本,路径固定为~/signalr/hubs --> <script src="~/signalr/hubs"></script>
然后写页面的HTML结构,包含添加输入框、按钮和展示列表的区域:
<div class="container mt-4"> <h2>实时同步Item列表</h2> <div class="mb-3"> <input type="text" id="newItemName" class="form-control w-50 d-inline-block" placeholder="输入Item名称" /> <button id="addItemBtn" class="btn btn-primary ms-2">添加Item</button> </div> <ul id="itemList" class="list-group w-50"> <!-- 这里会动态生成列表项 --> </ul> </div>
最后写JavaScript逻辑,实现连接Hub、获取初始数据、绑定增删事件,还有接收服务器的实时推送:
$(function () { // 创建ItemHub的代理对象 var itemHub = $.connection.itemHub; // 定义客户端的方法,服务器会调用这个方法来推送更新后的列表 itemHub.client.itemsUpdated = function (items) { renderItemList(items); }; // 启动SignalR连接 $.connection.hub.start().done(function () { console.log("已连接到SignalR Hub"); // 连接成功后,先获取当前所有Item来初始化列表 itemHub.server.getCurrentItems().done(function (items) { renderItemList(items); }); // 绑定添加按钮的点击事件 $('#addItemBtn').click(function () { var itemName = $('#newItemName').val().trim(); if (itemName) { // 调用Hub的AddItem方法 itemHub.server.addItem(itemName); $('#newItemName').val(''); // 清空输入框 } }); // 给动态生成的删除按钮绑定点击事件(用事件委托) $('#itemList').on('click', '.delete-btn', function () { var itemName = $(this).data('item-name'); // 调用Hub的DeleteItem方法 itemHub.server.deleteItem(itemName); }); }); // 渲染Item列表的辅助函数 function renderItemList(items) { var $list = $('#itemList'); $list.empty(); // 清空现有内容 if (items.length === 0) { $list.append('<li class="list-group-item">暂无Item,添加一个试试吧!</li>'); return; } // 遍历生成每个列表项,带删除按钮 items.forEach(function (item) { var listItem = $('<li>').addClass('list-group-item d-flex justify-content-between align-items-center') .text(item.Name); var deleteBtn = $('<button>').addClass('btn btn-sm btn-danger delete-btn') .text('删除') .data('item-name', item.Name); listItem.append(deleteBtn); $list.append(listItem); }); } });
四、测试功能
现在启动你的ASP.NET MVC应用,打开多个浏览器窗口(或者用隐私模式开多个窗口),在任意一个窗口添加或删除Item,你会看到所有窗口的列表都会实时同步更新,完美实现了跨客户端的实时交互!
内容的提问来源于stack exchange,提问作者millie
相关产品推荐
相关产品推荐

