上次講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依賴注入框架中。javascript
要在ASP.NET Core 2.0中使用SignalR,要先引用Microsoft.AspNetCore.SignalR 、 Microsoft.AspNetCore.SignalR.Http 兩個Package包。html
目前ASP.NET Core 2.0與SignalR還都是Preview版本,因此NUGET上也找不到SignalR的程序包,想添加引用咱們就得去MyGet上去找找。既然要用MyGet的話,就要爲項目添加NuGet源了。java
在程序根目錄新建一個命爲NuGet.Config的文件內容以下:git
<?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>
添加上面提到的兩個包的引用:github
<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。npm
固然也能夠用dotnet cli 來添加包引用:json
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
咱們須要在Startup類中的 ConfigureServices方法中添加以下代碼:api
public void ConfigureServices(IServiceCollection services) { services.AddSignalR(); }
在Startup類中的Configure方法中添加以下代碼:app
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseStaticFiles(); app.UseSignalR(routes => { routes.MapHub<Chat>("hubs"); }); }
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}"); } }
在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下, 歡迎一塊兒交流。
.NET Core 開源學習羣:214741894