Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET CORE 2.0 Uses SignalR Technology

0.00/5 (No votes)
28 Sep 2017 1  
The ASP.NET Core 1.x.x release does not include SignalR technology and development plans. Time has passed quickly, Microsoft has released a preview version of. NET Core 2.0 Preview 2.

Introduction

The ASP.NET Core 1.x.x release does not include SignalR technology and development plans. Time has passed quickly, Microsoft has released a preview version of. NET Core 2.0 Preview 2, not far from the official version, the above also mentioned in the ASP.NET Core 2.0 SignalR will be as important components and MVC and other frameworks released together. Its development team also fulfilled the commitment to use TypeScript to rewrite its JavaScript client, the server side will be close to the ASP.NET Core development, such as will be integrated into the ASP.NET Core dependent injection framework.

Environment to Build

To use SignalR in ASP.NET Core 2.0, first reference Microsoft.AspNetCore.SignalR, Microsoft.AspNetCore.SignalR.Http two package packages.

At present, ASP.NET Core 2.0 and SignalR are also in a preview version, so NuGet cannot find the SignalR package, would like to add a reference we have to go to MyGet look up. Since the use of MyGet, it is necessary to add NuGet source for the project.

Add the NuGet Source

In the program root directory, to create a new file for the NuGet.Config contents are as follows:

<?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>

Edit the Project File csproj

Add the references to the two packages mentioned above:

<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-alpha1-final" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Http" Version="0.0.1-alpha" />

I am using the current highest in this example, of course the version number is likely to change every day, the latest version of the SignalR is not compatible with the .NET Core SDK 2.0 Preview 1 by default when creating the project Microsoft.AspNetCore.All this package Version, also modify the revised version number here: Microsoft.AspNetCore.All 2.0.0-preview3-26040.

Of course, you can also use dotnet cli to add the package reference:

dotnet add package Microsoft.AspNetCore.SignalR --version 1.0.1-alpha-final 
--source https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json

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

Add the Configuration Code

We need to Startup class in the ConfigureServices method to add the following code:

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

Add the following code to the Configure method in the Startup class:

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

Add a HUB Class

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}");
    }
}

Client Support

In the wwwroot directory to create a chat.html called HTML static file, reads as follows:

<!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>

It is worth noting that you may find that there is no signalr-client.js in this document, how does it come, there are two ways:

The first way is to download the SignalR source code, find the Client-TS project, compile the TypeScript can be obtained.

The second kind of relatively simple way is through Npm which can be obtained online:

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here