SignalR的初步学习

一、使用场景:

客户端与服务端实时通讯,服务端主动向客户端发送消息;

二、分类:

1 websockets:单个TCP连接上的全双工通信协议;

2 SSE:Server-Sent Events:单向,服务器端主动向客户端推送消息;

3 Long Polling(长轮询)

三、问题

1 本机调试出现以下错误:

POST http://localhost:10145/NotificationHub/negotiate?negotiateVersion=1 500 (Internal Server Error)

Error: Failed to complete negotiation with the server: Error: System.MissingMethodException: Method not found: 'Microsoft.AspNetCore.Http.Features.IFeatureCollection Microsoft.AspNetCore.Connections.ConnectionContext.get_Features()'. at Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionContext..ctor(String connectionId, String connectionToken, ILogger logger) at Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager.CreateConnection(PipeOptions transportPipeOptions, PipeOptions appPipeOptions, Int32 negotiateVersion)

---原因:通过Nuget安装的signalr包错误

---解决方案:使用Microsoft.AspNet.SignalR.Core包

2 Clients.All.SendAsync出现未将对象引用设置到对象的异常:Clients未Null值

--原因:之前的写法hub对象与客户端的hub对象不是同一个,需要手动依赖注入一下

原写法:public class NotificationHub:Hub
    {
        public async Task SendNotification(string message)
        {
            var connId = "test:";//this.Context.ConnectionId;
            var msg = $"{connId}{DateTime.Now.ToString()}:{message}";
            await Clients.All.SendAsync("ReceiveNotification", msg);
        }
    }

---解决方案:

public class NotificationHub:Hub
    {
        private IHubContext<NotificationHub> _notificationHub { get; }

        public NotificationHub(IHubContext<NotificationHub> notificationHub)
        {
            this._notificationHub = notificationHub;
        }
        public async Task SendNotification(string message)
        {
            var connId = "test:";//this.Context.ConnectionId;
            var msg = $"{connId}{DateTime.Now.ToString()}:{message}";
            await _notificationHub.Clients.All.SendAsync("ReceiveNotification", msg);
        }
    }

四、完整代码:

1 前端显示页-razor页面 Index.cshtml

@page
@model TodoApi.Pages.SignalR.IndexModel
@{
}
<h1>SignalR for Notification Demo</h1>
<div id="notification-container"></div>

@section Scripts{
    <script src="~/js/signalr/dist/browser/signalr.js"></script>

    <script>
        //创建signalr hub客户端链接
        var connection = new signalR.HubConnectionBuilder()
            .withUrl("/NotificationHub")
            .build();

       

        //监听接收通知的回调函数
        connection.on("ReceiveNotification", function (message) {
            //在页面上显示接收到的通知
            displayNotification(message);
        });

       


        //连接建立后的回调函数
        connection.start().then(function () {
            console.log("Connected to the SignalR Hub!");
        }).catch(function (err) {
            return console.error(err.toString());
        });

        //显示通知的函数
        function displayNotification(message) {
            //更新页面元素
            var notificationContainer = document.getElementById("notification-container");
            notificationContainer.innerHTML += "<p>" + message + "</p>";
        }

    </script>
}

2 后端Hub类:

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

namespace TodoApi.SignalR
{
    public class NotificationHub:Hub
    {
        private IHubContext<NotificationHub> _notificationHub { get; }

        public NotificationHub(IHubContext<NotificationHub> notificationHub)
        {
            this._notificationHub = notificationHub;
        }
        public async Task SendNotification(string message)
        {
            var connId = "test:";//this.Context.ConnectionId;
            var msg = $"{connId}{DateTime.Now.ToString()}:{message}";
            await _notificationHub.Clients.All.SendAsync("ReceiveNotification", msg);
        }
    }
}

3.后端调用方法和依赖注入:

依赖注入Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ 
            app.UseEndpoints(endpoints =>
            {
               
                endpoints.MapHub<NotificationHub>("/NotificationHub");
                endpoints.MapHub<NotificationHub>("/ChatHub");
            });
}

 public void ConfigureServices(IServiceCollection services)
{
            //添加signalr服务
            services.AddSignalR();
              //添加依赖注入项:controller的构造函数中传递两个参数
            services.AddScoped<TodoContext>();
            services.AddScoped<NotificationHub>();
}

后端调用:

 public class TodoItemsController : ControllerBase
    {
        private readonly TodoContext _context;
        private readonly NotificationHub _hubContext;

        public TodoItemsController(TodoContext context,NotificationHub hubContext)
        {
            _context = context;
            _hubContext = hubContext;
        }

        
           [HttpGet("{id}")]
        public async Task<ActionResult<TodoItemDto>> GetTodoItem(long id)
        {
            var todoItem = await _context.TodoItems.FindAsync(id);

            if (todoItem == null)
            {
                return NotFound();
            }
            await _hubContext.SendNotification($"获取了一次数据:{id}");
            return ItemToDTO(todoItem);
        }
    }

  • 35
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值