SignalR在Asp.NetCore的使用入门

SignalR在ASP.NET CORE下的使用

SignalR是微软提供的实时Web通信的库

它会自己根据情况使用不同的链接方式,主要有

  • WebSocket
  • long polling
  • Forever frame
  • Sever Events Sent

等方式,故可以不管其具体的实现方式,差不多等于开箱即用了。

一.StartUp中的起始配置

在StartUp中添加配置

public void ConfigureServices(IServiceCollection services)
{
    
    
    services.AddRazorPages();
    services.AddSignalR();     //只需要添加AddSignalR
    services.AddControllers();
    
    services.AddCors(options =>
    options.AddPolicy("lingluAllCors",
    p => 	p.AllowAnyOrigin().
              AllowAnyHeader().
              AllowAnyMethod()));
    #endregion
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    
    
    if (env.IsDevelopment())
    {
    
    
        app.UseDeveloperExceptionPage();
    }
    else
    {
    
    
        app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
    
    
        endpoints.MapControllers();
        endpoints.MapRazorPages();
        //添加/注册对应的Hub类,并添加路由
        //请注意:在不同的.Net Core版本中,MapHub方法也可能在app中
        //如果找不到MapHub请两个地方都试一试
        endpoints.MapHub<ChatHub>("/chatHub");
    });

    app.UseCors("lingluAllCors");
}

二.配置Hub中心类和服务器推送信息

Hub类是SignalR的核心工具类

它主要有两个功能

1. 向Client(浏览器)的监听处主动推送消息【服务器主动推送数据】

2.接受Client的发起的信息(请求),【普通的请求----->响应模式】

例:Hub类的简单解释

public class ChatHub : Hub
{
    
    
	//继承Hub类可以复写
    //Task OnDisconnectedAsync(Exception exception)
    //Task OnConnectedAsync()
    //以上方法在Client链接/断开时被触发,而推送/接受信息的方法则需要你自定义
    
    //Hub里的方法不在后台调用,而是通过函数名和参数在前端进行js调用
    public async Task SendMessage(string user, string message)
    {
    
    
        //这里和普通的 请求---->响应 的方式很像
        //在这里拿到参数,写一些逻辑
		Console.WriteLine("User is" + user + " | Message is"+message);
        
        //但区别在于,你可以选择是否响应
        //这个SendAsync在下一小节细讲
        //Clients.All.SendAsync("ReceiveMessage2", user, message);
    }

	
    //如果请求需要返回,也可以多次返回(或是一些有条件的返回)
    public async Task SendMessage2(string user, string message)
    {
    
    

        await Clients.All.SendAsync("ReceiveMessage2", user, message);

        for (int i = 0; i < 10; i++)
        {
    
    
            Thread.Sleep(2000);
            await Clients.All.SendAsync("ReceiveMessage2","van you see","luckshit");
        }
    }


   
}

例:服务器主动推送消息给前端

当你完成自定义Hub类,并把它注册到StartUp中,

你就能通过ASP.NET CORE自带的DI(依赖注入)

获取该类型(你自定义的Hub)泛型的IHubContext对象,

然后后台就可以在链接存在时随时的推送数据了

以一个Controller为例:

[Route("api/[controller]/[action]")]
[ApiController]
public class SendController : ControllerBase
{
    
    
    //可以通过DI来获取指定的自定义中心泛型的IHubContext工具
    private readonly IHubContext<ChatHub> _hubContext;

    public SendController(IHubContext<ChatHub> hubContext)
    {
    
    
        _hubContext = hubContext;
    }

    
    [HttpGet]
    public async Task<string> SendData(string message)
    {
    
    
        //给前端监听的ReceiveMessage2方法传递参数
        await _hubContext.Clients.All.SendAsync("ReceiveMessage2", "van you see", "luckshit");

        return "something you want";
    }
}

三.前端代码和显示

前端的显示

需要微软提供的js文件

如果你使用node.js的话,可以在直接npm install下来,不使用的话也可以直接引入js文件

npm install @microsoft/signalr
# or
yarn add @microsoft/signalr

链接:

@microsoft/signalr - npm (npmjs.com)

在项目中创建页面,然后引入js

在这里插入图片描述

页面代码:

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>

    <div class="container">
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-2">User</div>
            <div class="col-4"><input type="text" id="userInput" /></div>
        </div>
        <div class="row">
            <div class="col-2">Message</div>
            <div class="col-4"><input type="text" id="messageInput" /></div>
        </div>
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-6">
                <input type="button" id="sendButton" value="Send Message" />
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-12">
            <hr />
        </div>
    </div>
    <div class="row">
        <div class="col-6">
            <ul id="messagesList"></ul>
        </div>
    </div>
    <!--引入js文件-->
    <script src="./lib/microsoft/signalr/dist/browser/signalr.js"></script>

    <script>
       
        //初始化客户端 官网 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-5.0&tabs=visual-studio

        //创建链接并指定到在StartUp中配置的Chathub的路由,
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/chathub")
            .configureLogging(signalR.LogLevel.Information)
            .build();

        //start开始连接,
        async function start() {
      
      
            try {
      
      
                //会在后台触发连接Hub的Task OnConnectedAsync()方法,
                await connection.start();
                
                //如果想要在链接处获取身份信息,即使用/获取自带的UserID/Group对象什么的,
                //需要使用ASP.NET CORE 官方的authorize, 和Identity的相关内容,如果使用的是自研的登陆和认证内容,则无法使用以上的user对象
                //请手动发送empno/username等信息
                
                console.log("SignalR Connected.");
                console.log(connection.connectionId);
                
            } catch (err) {
      
      
                console.log(err);
                //异步发起重连
                setTimeout(start, 5000);
            }
        };

        //重连机制
        connection.onclose(async () => {
      
      
            await start();
        });

        //ReceiveMessage2为监听的数据标识,可自定义
        //解释:当后台调用hub对象(IHubContext)SendAsync时,指定的第一个参数即为此标识时(或者直说第一个method参数等于此标识时),则前端会自动调用对应的函数,
        //      后台的返回值则会注入到前端的参数中
        connection.on("ReceiveMessage2", function (user, message) {
      
      

            //UI显示监听的数据
            var li = document.createElement("li");
            document.getElementById("messagesList").appendChild(li);
            li.textContent = `ReceiveMessage2:${ 
        user} says ${ 
        message}`;


        });



        //发起连接
        start();



        //按钮事件(发送链接)
        document.getElementById("sendButton").addEventListener("click", function (event) {
      
      
            var user = document.getElementById("userInput").value;
            var message = document.getElementById("messageInput").value;

            SendMessage2为自定义方法ChatHub.cs 定义的相同
            connection.invoke("SendMessage2", user, message).catch(function (err) {
      
      
                return console.error(err.toString());
            });

            event.preventDefault();
        });
    </script>
</body>
</html>

四.运行和测试

后台推送信息给前台

运行程序,开打页面和开发者工具

在这里插入图片描述

然后,调用Controller中的测试方法 api/Send/SendData

在这里插入图片描述

调用Hub对象(IHubContext)的SendAsync方法

在这里插入图片描述

然后再回到前端查看页面的效果

在这里插入图片描述

常规的前端请求到后台(在Signalr中可以不作响应)

在页面的输入框中输入数据,提交去触发前端 hubconnection的invoke方法,

后台调用invoke指定的Hub类的方法
(定义的Hub类中的对应方法,注意:这里的Hub类不是Hub对象(IHubContext))

在这里插入图片描述

然后在方法体中给前端的监听函数推送信息。

在这里插入图片描述

这种方式就和请求响应的模式很接近,但是也可以不响应(情况比较少)。

测试小节总结

一定要弄清Hub类的作用,

  • Hub类中定义的方法为只能被前端invoke调用,但是否响应(SendAsync)是可选的
  • 当你在其他的地方要推送信息(SendAsync)时,使用的是IHubContext
  • IHubContext可以使用DI,你可以在后台的任何地方自动发送消息
  • 不要尝试将IHubContext 转化为T,后台无法调用Hub类方法,路已被锁死
补充

Hub可以获取指定Client,
并有一套API和ASP.NET CORE 的Autherize,Identity配合可以
获取User,Group,Auth…的信息,
如果你的程序没有用到ASP.NET CORE的Authrize,那就用不了。
但是可以在连接开始阶段发送用户信息,然后借以统计是否存在链接/对手链接

https://download.csdn.net/download/jamenu/87380909?spm=1001.2014.3001.5501

不要尝试将IHubContext 转化为T,后台无法调用Hub类方法,路已被锁死

猜你喜欢

转载自blog.csdn.net/jamenu/article/details/128661621