zoukankan      html  css  js  c++  java
  • 在ASP.NET CORE 2.0使用SignalR技术

    一、前言

    上次讲SignalR还是在《在ASP.NET Core下使用SignalR技术》文章中提到,ASP.NET Core 1.x.x 版本发布中并没有包含SignalR技术和开发计划中。时间过得很快,MS已经发布了.NET Core 2.0 Preview 2 预览版,距离正式版已经不远了,上文中也提到过在ASP.NET Core 2.0中的SignalR将做为重要的组件与MVC等框架一起发布。它的开发团队也兑现了承诺,使用TypeScript对它的javascript客户端进行重写,服务端方面也会贴近ASP.NET Core的开发方式,比如会集成到ASP.NET Core依赖注入框架中。

    二、环境搭建

    要在ASP.NET Core 2.0中使用SignalR,要先引用Microsoft.AspNetCore.SignalR 、 Microsoft.AspNetCore.SignalR.Http 两个Package包。

    目前ASP.NET Core 2.0与SignalR还都是Preview版本,所以NUGET上也找不到SignalR的程序包,想添加引用我们就得去MyGet上去找找。既然要用MyGet的话,就要为项目添加NuGet源了。

    1.添加NuGet源

    在程序根目录新建一个命为NuGet.Config的文件内容如下:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <packageSources>
            <clear/>
                <add key="aspnetcidev" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json"/>
                <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json"/>
        </packageSources>
    </configuration>

    2.编辑项目文件csproj

    添加上面提到的两个包的引用:

        <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview3-26040" />
        <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-preview3-26037" />
        <PackageReference Include="Microsoft.AspNetCore.SignalR.Http" Version="1.0.0-preview3-26037" />

    我在这个示例里使用的是目前的最高,当然版本号每天都有可能发生变化,最新版本的SignalR,是不兼容.NET Core SDK 2.0 Preview 1中默认创建项目时Microsoft.AspNetCore.All这个包的版本的,这里也修改修改一下版本号为:Microsoft.AspNetCore.All 2.0.0-preview3-26040。

    当然也可以用dotnet cli 来添加包引用:

    dotnet add package Microsoft.AspNetCore.SignalR --version 1.0.0-preview3-26037 --source https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json
    
    dotnet add package Microsoft.AspNetCore.SignalR.Http --version 1.0.0-preview3-26037 --source https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json

    3.添加配置代码

    我们需要在Startup类中的 ConfigureServices方法中添加如下代码:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSignalR();
    }

    在Startup类中的Configure方法中添加如下代码:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseStaticFiles();
        app.UseSignalR(routes =>
        {
            routes.MapHub<Chat>("hubs");
        });
    }

    4.添加一个HUB类

    public class Chat : Hub
    {
        public override async Task OnConnectedAsync()
        {
            await Clients.All.InvokeAsync("Send", $"{Context.ConnectionId} joined");
        }
    
        public override async Task OnDisconnectedAsync(Exception ex)
        {
            await Clients.All.InvokeAsync("Send", $"{Context.ConnectionId} left");
        }
    
        public Task Send(string message)
        {
            return Clients.All.InvokeAsync("Send", $"{Context.ConnectionId}: {message}");
        }
    
        public Task SendToGroup(string groupName, string message)
        {
            return Clients.Group(groupName).InvokeAsync("Send", $"{Context.ConnectionId}@{groupName}: {message}");
        }
    
        public async Task JoinGroup(string groupName)
        {
            await Groups.AddAsync(Context.ConnectionId, groupName);
    
            await Clients.Group(groupName).InvokeAsync("Send", $"{Context.ConnectionId} joined {groupName}");
        }
    
        public async Task LeaveGroup(string groupName)
        {
            await Groups.RemoveAsync(Context.ConnectionId, groupName);
    
            await Clients.Group(groupName).InvokeAsync("Send", $"{Context.ConnectionId} left {groupName}");
        }
    
        public Task Echo(string message)
        {
            return Clients.Client(Context.ConnectionId).InvokeAsync("Send", $"{Context.ConnectionId}: {message}");
        }
    }

    5.客户端支持

      在wwwroot目录下创建一个名为chat.html的Html静态文件,内容如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <h1 id="head1"></h1>
        <div>
            <select id="formatType">
                <option value="json">json</option>
                <option value="line">line</option>
            </select>
    
            <input type="button" id="connect" value="Connect" />
            <input type="button" id="disconnect" value="Disconnect" />
        </div>
    
    
        <h4>To Everybody</h4>
        <form class="form-inline">
            <div class="input-append">
                <input type="text" id="message-text" placeholder="Type a message, name or group" />
                <input type="button" id="broadcast" class="btn" value="Broadcast" />
                <input type="button" id="broadcast-exceptme" class="btn" value="Broadcast (All Except Me)" />
                <input type="button" id="join" class="btn" value="Enter Name" />
                <input type="button" id="join-group" class="btn" value="Join Group" />
                <input type="button" id="leave-group" class="btn" value="Leave Group" />
            </div>
        </form>
    
        <h4>To Me</h4>
        <form class="form-inline">
            <div class="input-append">
                <input type="text" id="me-message-text" placeholder="Type a message" />
                <input type="button" id="send" class="btn" value="Send to me" />
            </div>
        </form>
    
        <h4>Private Message</h4>
        <form class="form-inline">
            <div class="input-prepend input-append">
                <input type="text" name="private-message" id="private-message-text" placeholder="Type a message" />
                <input type="text" name="user" id="target" placeholder="Type a user or group name" />
    
                <input type="button" id="privatemsg" class="btn" value="Send to user" />
                <input type="button" id="groupmsg" class="btn" value="Send to group" />
            </div>
        </form>
    
        <ul id="message-list"></ul>
    </body>
    </html>
    <script src="signalr-client.js"></script>
    <script src="utils.js"></script>
    <script>
    var isConnected = false;
    function invoke(connection, method, ...args) {
        if (!isConnected) {
            return;
        }
        var argsArray = Array.prototype.slice.call(arguments);
        connection.invoke.apply(connection, argsArray.slice(1))
                .then(result => {
                    console.log("invocation completed successfully: " + (result === null ? '(null)' : result));
    
                    if (result) {
                        addLine('message-list', result);
                    }
                })
                .catch(err => {
                    addLine('message-list', err, 'red');
                });
    }
    
    function getText(id) {
        return document.getElementById(id).value;
    }
    
    let transportType = signalR.TransportType[getParameterByName('transport')] || signalR.TransportType.WebSockets;
    
    document.getElementById('head1').innerHTML = signalR.TransportType[transportType];
    
    let connectButton = document.getElementById('connect');
    let disconnectButton = document.getElementById('disconnect');
    disconnectButton.disabled = true;
    var connection;
    
    click('connect', event => {
        connectButton.disabled = true;
        disconnectButton.disabled = false;
        let http = new signalR.HttpConnection(`http://${document.location.host}/hubs`, { transport: transportType });
        connection = new signalR.HubConnection(http);
        connection.on('Send', msg => {
            addLine('message-list', msg);
        });
    
        connection.onClosed = e => {
            if (e) {
                addLine('message-list', 'Connection closed with error: ' + e, 'red');
            }
            else {
                addLine('message-list', 'Disconnected', 'green');
            }
        }
    
        connection.start()
            .then(() => {
                isConnected = true;
                addLine('message-list', 'Connected successfully', 'green');
            })
            .catch(err => {
                addLine('message-list', err, 'red');
            });
    });
    
    click('disconnect', event => {
        connectButton.disabled = false;
        disconnectButton.disabled = true;
        connection.stop()
            .then(() => {
                isConnected = false;
            });
    });
    
    click('broadcast', event => {
        let data = getText('message-text');
        invoke(connection, 'Send', data);
    });
    
    click('join-group', event => {
        let groupName = getText('message-text');
        invoke(connection, 'JoinGroup', groupName);
    });
    
    click('leave-group', event => {
        let groupName = getText('message-text');
        invoke(connection, 'LeaveGroup', groupName);
    });
    
    click('groupmsg', event => {
        let groupName = getText('target');
        let message = getText('private-message-text');
        invoke(connection, 'SendToGroup', groupName, message);
    });
    
    click('send', event => {
        let data = getText('me-message-text');
        invoke(connection, 'Echo', data);
    });
    
    </script>

    值得注意的是,你可能会发现,目前找不到signalr-client.js这个文件,它是怎么来的呢,有两种方式:
    第1种是通过下载SignalR的源代码,找到Client-TS项目,对TypeScript进行编译可以得到。

    第2种比较简单通过Npm可以在线获取:

    npm install signalr-client --registry https://dotnet.myget.org/f/aspnetcore-ci-dev/npm/

    三、最后

      附上一个可用的Demo:https://github.com/maxzhang1985/AspNetCore.SignalRDemo

      GitHub:https://github.com/maxzhang1985/YOYOFx 如果觉还可以请Star下, 欢迎一起交流。

  • 相关阅读:
    Codeforces Canda Cup 2016
    Codeforces Round #377(div 2)
    后缀数组专题
    Codeforces Round #375(div 2)
    Codeforces Round #374(div 2)
    [HDU5902]GCD is Funny(xjb搞)
    [HDU5904]LCIS(DP)
    HDU 1251统计难题
    POJ2104 K-TH NUMBER 传说中的主席树
    poj 3041
  • 原文地址:https://www.cnblogs.com/sky-net/p/8668620.html
Copyright © 2011-2022 走看看