This article shows how to setup a first SignalR Hub in ASP.NET Core 2.0 and use it with an Angular client. SignalR will be released with dotnet 2.1. Thanks to Dennis Alberti for his help in setting up the code example.
Code: https://github.com/damienbod/AspNetCoreAngularSignalR
2017-09-15: Updated @aspnet/signalr-client to use npm feed, and 1.0.0-alpha1-final
The required SignalR Nuget packages and npm packages are at present hosted on MyGet. Your need to add the SignalR packagesto the csproj file. To use the MyGet feed, add the https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json to your package sources.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-alpha1-final" /> </ItemGroup> <ItemGroup> <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" /> <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" /> </ItemGroup> <ItemGroup> <Folder Include="angularApp\app\models\" /> </ItemGroup> </Project>
Now create a simple default hub.
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace AspNetCoreSignalr.SignalRHubs { public class LoopyHub : Hub { public Task Send(string data) { return Clients.All.InvokeAsync("Send", data); } } }
Add the SignalR configuration in the startup class. The hub which was created before needs to be added in the UseSignalR extension method.
public void ConfigureServices(IServiceCollection services) { ... services.AddSignalR(); ... } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { ... app.UseSignalR(routes => { routes.MapHub<LoopyHub>("loopy"); }); ... }
Setup the Angular application. The Angular application is setup using a wepback build and all dependencies are added to the packages.json file.
You can use the The MyGet npm feed if you want to use the aspnetcore-ci-dev. You can do this using a .npmrc file in the project root. Add the registry path. If using the npm package, do not add this.
@aspnet:registry=https://dotnet.myget.org/f/aspnetcore-ci-dev/npm/
Now add the required SignalR npm packages to the packages.json file. Using the npm package from NuGet:
"dependencies": { "@angular/animations": "4.4.0-RC.0", "@angular/common": "4.4.0-RC.0", "@angular/compiler": "4.4.0-RC.0", "@angular/compiler-cli": "4.4.0-RC.0", "@angular/core": "4.4.0-RC.0", "@angular/forms": "4.4.0-RC.0", "@angular/http": "4.4.0-RC.0", "@angular/platform-browser": "4.4.0-RC.0", "@angular/platform-browser-dynamic": "4.4.0-RC.0", "@angular/platform-server": "4.4.0-RC.0", "@angular/router": "4.4.0-RC.0", "@angular/upgrade": "4.4.0-RC.0", "msgpack5": "^3.5.1", "@aspnet/signalr-client": "1.0.0-alpha1-final" },
Add the SignalR client code. In this basic example, it is just added directly in a component. The sendMessage funtion sends messages and the hubConnection.on function recieves all messages including its own.
import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { HubConnection } from '@aspnet/signalr-client'; @Component({ selector: 'app-home-component', templateUrl: './home.component.html' }) export class HomeComponent implements OnInit { private _hubConnection: HubConnection; public async: any; message = ''; messages: string[] = []; constructor() { } public sendMessage(): void { const data = `Sent: ${this.message}`; this._hubConnection.invoke('Send', data); this.messages.push(data); } ngOnInit() { this._hubConnection = new HubConnection('/loopy'); this._hubConnection.on('Send', (data: any) => { const recieved = `Recieved: ${data}`; this.messages.push(recieved); }); this._hubConnection.start() .then(() => { console.log('Hub connection started') }) .catch(err => { console.log('Error while establishing connection') }); } }
The messages are then displayed in the component template.
<div class="container-fluid"> <h1>Send some basic messages</h1> <div class="row"> <form class="form-inline" (ngSubmit)="sendMessage()" #messageForm="ngForm"> <div class="form-group"> <label class="sr-only" for="message">Message</label> <input type="text" class="form-control" id="message" placeholder="your message..." name="message" [(ngModel)]="message" required> </div> <button type="submit" class="btn btn-primary" [disabled]="!messageForm.valid">Send SignalR Message</button> </form> </div> <div class="row" *ngIf="messages.length > 0"> <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>#</th> <th>Messages</th> </tr> </thead> <tbody> <tr *ngFor="let message of messages; let i = index"> <td>{{i + 1}}</td> <td>{{message}}</td> </tr> </tbody> </table> </div> </div> <div class="row" *ngIf="messages.length <= 0"> <span>No messages</span> </div> </div>
Now the first really simple SignalR Hub is setup and an Angular client can send and recieve messages.
Links:
https://github.com/aspnet/SignalR#readme
https://www.npmjs.com/package/@aspnet/signalr-client
https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json
https://dotnet.myget.org/F/aspnetcore-ci-dev/npm/
https://dotnet.myget.org/feed/aspnetcore-ci-dev/package/npm/@aspnet/signalr-client
https://www.npmjs.com/package/msgpack5
