├── .gitignore ├── Dockerfile ├── Hubs ├── ChatHub.cs ├── GraphHub.cs ├── ProcessHub.cs └── StockHub.cs ├── LICENSE ├── Models └── Stock.cs ├── Program.cs ├── Properties └── launchSettings.json ├── Startup.cs ├── TopSwagCode.SignalR.csproj ├── TopSwagCode.SignalR.sln ├── appsettings.Development.json ├── appsettings.json ├── chatapp.gif ├── graphapp.gif ├── processingapp.gif ├── readme.md ├── services ├── FakeStockService.cs ├── IStockService.cs ├── StockHostedService.cs └── TimedHostedService.cs ├── stockapp.gif └── wwwroot ├── assets └── topswagcode.png ├── chat └── index.html ├── graph └── index.html ├── index.html ├── js ├── chat-app.js ├── graph-app.js ├── processing-app.js ├── signalr.js └── stock-app.js ├── processing └── index.html └── stock └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.swp 3 | *.*~ 4 | project.lock.json 5 | .DS_Store 6 | *.pyc 7 | nupkg/ 8 | 9 | # Visual Studio Code 10 | .vscode 11 | 12 | # User-specific files 13 | *.suo 14 | *.user 15 | *.userosscache 16 | *.sln.docstates 17 | 18 | # Build results 19 | [Dd]ebug/ 20 | [Dd]ebugPublic/ 21 | [Rr]elease/ 22 | [Rr]eleases/ 23 | x64/ 24 | x86/ 25 | build/ 26 | bld/ 27 | [Bb]in/ 28 | [Oo]bj/ 29 | [Oo]ut/ 30 | msbuild.log 31 | msbuild.err 32 | msbuild.wrn 33 | 34 | # Visual Studio 2015 35 | .vs/ -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:sdk AS build-env 2 | WORKDIR /app 3 | 4 | # Copy csproj and restore as distinct layers 5 | COPY *.csproj ./ 6 | RUN dotnet restore 7 | 8 | # Copy everything else and build 9 | COPY . ./ 10 | RUN dotnet publish -c Release -o out 11 | 12 | # Build runtime image 13 | FROM microsoft/dotnet:aspnetcore-runtime 14 | WORKDIR /app 15 | COPY --from=build-env /app/out . 16 | ENTRYPOINT ["dotnet", "TopSwagCode.SignalR.dll"] -------------------------------------------------------------------------------- /Hubs/ChatHub.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.SignalR; 3 | 4 | namespace TopSwagCode.SignalR.Hubs 5 | { 6 | public class ChatHub : Hub 7 | { 8 | public async Task SendMessage(string user, string message) 9 | { 10 | await Clients.All.SendAsync("ReceiveMessage", user,message); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Hubs/GraphHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | 3 | namespace TopSwagCode.SignalR.Hubs 4 | { 5 | public class GraphHub : Hub 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Hubs/ProcessHub.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.SignalR; 3 | 4 | namespace TopSwagCode.SignalR.Hubs 5 | { 6 | public class ProcessHub : Hub 7 | { 8 | public async Task StartProcessing() 9 | { 10 | for (int i = 0; i <= 100; i += 5) 11 | { 12 | await Clients.Caller.SendAsync("process", i); 13 | await Task.Delay(75); 14 | } 15 | 16 | await Task.Delay(2000); 17 | 18 | await Clients.Caller.SendAsync("processDone", "/assets/topswagcode.png"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Hubs/StockHub.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.SignalR; 3 | using Newtonsoft.Json; 4 | using TopSwagCode.SignalR.services; 5 | 6 | namespace TopSwagCode.SignalR.Hubs 7 | { 8 | public class StockHub : Hub 9 | { 10 | private readonly IStockService _stockService; 11 | 12 | public StockHub(IStockService stockService) 13 | { 14 | _stockService = stockService; 15 | } 16 | 17 | public override async Task OnConnectedAsync() 18 | { 19 | var stocks = _stockService.GetAllStocks(); 20 | 21 | var jsonString = JsonConvert.SerializeObject(stocks); 22 | 23 | await Clients.Caller.SendAsync("UpdateStocks", jsonString); 24 | 25 | await base.OnConnectedAsync(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Joshua Jesper Krægpøth Ryder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Models/Stock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Newtonsoft.Json; 6 | 7 | namespace TopSwagCode.SignalR.Models 8 | { 9 | public class Stock 10 | { 11 | [JsonProperty("symbol")] 12 | public string Symbol { get; set; } 13 | [JsonProperty("bid")] 14 | public double Bid { get; set; } 15 | [JsonProperty("ask")] 16 | public double Ask { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace TopSwagCode.SignalR 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 14 | WebHost.CreateDefaultBuilder(args) 15 | .UseStartup(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:51131/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "TopSwagCode.SignalR": { 19 | "commandName": "Project", 20 | "launchBrowser": false, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:51133/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using TopSwagCode.SignalR.Hubs; 6 | using TopSwagCode.SignalR.services; 7 | 8 | namespace TopSwagCode.SignalR 9 | { 10 | public class Startup 11 | { 12 | private readonly IHostingEnvironment _environment; 13 | 14 | public Startup(IConfiguration configuration, IHostingEnvironment environment) 15 | { 16 | _environment = environment; 17 | Configuration = configuration; 18 | } 19 | 20 | public IConfiguration Configuration { get; } 21 | 22 | public void ConfigureServices(IServiceCollection services) 23 | { 24 | services.AddCors(options => options.AddPolicy("CorsPolicy", 25 | builder => 26 | { 27 | if (_environment.IsDevelopment()) 28 | { 29 | builder.AllowAnyMethod() 30 | .AllowAnyHeader() 31 | .WithOrigins("http://localhost:4000") 32 | .AllowCredentials(); 33 | } 34 | else 35 | { 36 | builder.AllowAnyMethod() 37 | .AllowAnyHeader() 38 | .WithOrigins("http://localhost:4000", "http://127.0.0.1:4000", "https://topswagcode.com") 39 | .AllowCredentials(); 40 | } 41 | })); 42 | 43 | services.AddTransient(); 44 | services.AddHostedService(); 45 | services.AddHostedService(); 46 | 47 | services.AddSignalR(); 48 | } 49 | 50 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 51 | { 52 | app.UseFileServer(); 53 | 54 | app.UseCors("CorsPolicy"); 55 | 56 | app.UseSignalR(route => 57 | { 58 | route.MapHub("/chathub"); 59 | route.MapHub("/processhub"); 60 | route.MapHub("/graphhub"); 61 | route.MapHub("/stockhub"); 62 | }); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /TopSwagCode.SignalR.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | 1c4b8384-23cc-46b6-a537-1f8abb24dc46 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /TopSwagCode.SignalR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2027 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TopSwagCode.SignalR", "TopSwagCode.SignalR.csproj", "{F513C7FB-6991-4EAA-BF31-5FCB8B7909B3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F513C7FB-6991-4EAA-BF31-5FCB8B7909B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F513C7FB-6991-4EAA-BF31-5FCB8B7909B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F513C7FB-6991-4EAA-BF31-5FCB8B7909B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F513C7FB-6991-4EAA-BF31-5FCB8B7909B3}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CBB7A5ED-3756-4BC5-A282-02D093A765D0} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /chatapp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TopSwagCode/AspNetCore.SignalR/a08ae6c74627b8fb85e4911a34f0d12bc8b66625/chatapp.gif -------------------------------------------------------------------------------- /graphapp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TopSwagCode/AspNetCore.SignalR/a08ae6c74627b8fb85e4911a34f0d12bc8b66625/graphapp.gif -------------------------------------------------------------------------------- /processingapp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TopSwagCode/AspNetCore.SignalR/a08ae6c74627b8fb85e4911a34f0d12bc8b66625/processingapp.gif -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |  # AspNetCore.SignalR 2 | 3 | Small work in progress for showcasing stuff to do with WebSockets and how simple it is getting started :) 4 | 5 | Contains 4 small sample usages: 6 | 7 | * Chat -> Small simple chat between all users. 8 | * Graph -> Shows some numbers to all users. Eg. Admin dashboard. 9 | * Process -> Shows how you could offload some work but still keep your user informed on progress. 10 | * Stocks -> Show how to broadcast complex models using json. 11 | 12 | Run app locally: 13 | 14 | Start a http server on port 4000 in the wwwroot folder. (My goto is https://www.nuget.org/packages/dotnet-serve/) 15 | install the tool: 16 | 17 | ```console 18 | $ dotnet tool install --global dotnet-serve --version 1.2.0 19 | ``` 20 | 21 | run the tool: 22 | 23 | ```console 24 | $ dotnet-serve -p 4000 25 | ``` 26 | 27 | Now run the Dotnet project by running: 28 | 29 | ```console 30 | $ dotnet run 31 | ``` 32 | 33 | Or you could run the server with docker ;) 34 | 35 | ```console 36 | $ docker run --name topswagcode -p 51133:80 kiksen1987/signalr 37 | ``` 38 | 39 | Now open your browser of chouse at http://localhost:4000 and you should have links to the 4 demo apps as shown below: 40 | 41 | # Chat 42 | 43 | ![Chat App](chatapp.gif "Chat App") 44 | 45 | # Graph 46 | 47 | ![Graph App](graphapp.gif "Graph App") 48 | 49 | # Processing 50 | 51 | ![Processing App](processingapp.gif "Processing App") 52 | 53 | # Stock 54 | 55 | ![Stock App](stockapp.gif "Stock App") 56 | -------------------------------------------------------------------------------- /services/FakeStockService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using TopSwagCode.SignalR.Models; 6 | 7 | namespace TopSwagCode.SignalR.services 8 | { 9 | public class FakeStockService : IStockService 10 | { 11 | private readonly Random _random; 12 | 13 | public FakeStockService() 14 | { 15 | _random = new Random(); 16 | } 17 | 18 | public List GetChangedStocks() 19 | { 20 | var changedStocks = new List(); 21 | 22 | var numberOfChangedStock = _random.Next(0, 4); 23 | 24 | for (int i = 0; i < numberOfChangedStock; i++) 25 | { 26 | changedStocks.Add(new Stock 27 | { 28 | Ask = Math.Round(_random.NextDouble() * (200 - 10) + 10, 2), 29 | Bid = Math.Round(_random.NextDouble() * (200 - 10) + 10, 2), 30 | Symbol = randomStockNames[_random.Next(0, randomStockNames.Count)] 31 | }); 32 | } 33 | 34 | return changedStocks; 35 | } 36 | 37 | public List GetAllStocks() 38 | { 39 | var stocks = new List(); 40 | 41 | 42 | for (int i = 0; i < randomStockNames.Count; i++) 43 | { 44 | stocks.Add(new Stock 45 | { 46 | Ask = Math.Round(_random.NextDouble() * (200 - 10) + 10, 2), 47 | Bid = Math.Round(_random.NextDouble() * (200 - 10) + 10, 2), 48 | Symbol = randomStockNames[i] 49 | }); 50 | } 51 | 52 | return stocks; 53 | } 54 | 55 | List randomStockNames = new List 56 | { 57 | "AMZN", "TGT", "VNET", "CARB", "CCIH", "FB", "IAC", "JCOM", "EGOV", "NTES" 58 | }; 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /services/IStockService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using TopSwagCode.SignalR.Models; 3 | 4 | namespace TopSwagCode.SignalR.services 5 | { 6 | public interface IStockService 7 | { 8 | List GetChangedStocks(); 9 | List GetAllStocks(); 10 | } 11 | } -------------------------------------------------------------------------------- /services/StockHostedService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.SignalR; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | using Newtonsoft.Json; 10 | using TopSwagCode.SignalR.Hubs; 11 | using TopSwagCode.SignalR.Models; 12 | 13 | namespace TopSwagCode.SignalR.services 14 | { 15 | internal class StockHostedService : IHostedService, IDisposable 16 | { 17 | private readonly ILogger _logger; 18 | private Timer _timer; 19 | private readonly IHubContext _stockHubContext; 20 | private readonly IStockService _stockService; 21 | 22 | public StockHostedService(ILogger logger, IHubContext stockHubContext, IStockService stockService) 23 | { 24 | _logger = logger; 25 | _stockHubContext = stockHubContext; 26 | _stockService = stockService; 27 | } 28 | 29 | public Task StartAsync(CancellationToken cancellationToken) 30 | { 31 | _timer = new Timer(CheckForChangedStockAndPublishToClients, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(2000)); 32 | return Task.CompletedTask; 33 | } 34 | 35 | private void CheckForChangedStockAndPublishToClients(object state) 36 | { 37 | _logger.LogInformation("Timed Stock Background Service is working."); 38 | 39 | var stocks = _stockService.GetChangedStocks(); 40 | 41 | var jsonString = JsonConvert.SerializeObject(stocks); 42 | 43 | _stockHubContext.Clients.All.SendAsync("UpdateStocks", jsonString).GetAwaiter().GetResult(); 44 | } 45 | 46 | 47 | 48 | public Task StopAsync(CancellationToken cancellationToken) 49 | { 50 | _timer?.Change(Timeout.Infinite, 0); 51 | 52 | return Task.CompletedTask; 53 | } 54 | 55 | public void Dispose() 56 | { 57 | _timer?.Dispose(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /services/TimedHostedService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.SignalR; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.Extensions.Logging; 8 | using Newtonsoft.Json; 9 | using TopSwagCode.SignalR.Hubs; 10 | 11 | namespace TopSwagCode.SignalR.services 12 | { 13 | internal class TimedHostedService : IHostedService, IDisposable 14 | { 15 | private readonly ILogger _logger; 16 | private Timer _timer; 17 | private readonly IHubContext _graphHubContext; 18 | private readonly Random _random; 19 | 20 | public TimedHostedService(ILogger logger, IHubContext graphHubContext) 21 | { 22 | _logger = logger; 23 | _graphHubContext = graphHubContext; 24 | _random = new Random(); 25 | } 26 | 27 | public Task StartAsync(CancellationToken cancellationToken) 28 | { 29 | _logger.LogInformation("Timed Background Service is starting."); 30 | 31 | _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(500)); 32 | 33 | 34 | return Task.CompletedTask; 35 | } 36 | 37 | private void DoWork(object state) 38 | { 39 | _logger.LogInformation("Timed Background Service is working."); 40 | 41 | _graphHubContext.Clients.All.SendAsync("LogWork", _random.Next(0,100).ToString()).GetAwaiter().GetResult(); 42 | 43 | } 44 | 45 | public Task StopAsync(CancellationToken cancellationToken) 46 | { 47 | _logger.LogInformation("Timed Background Service is stopping."); 48 | 49 | _timer?.Change(Timeout.Infinite, 0); 50 | 51 | return Task.CompletedTask; 52 | } 53 | 54 | public void Dispose() 55 | { 56 | _timer?.Dispose(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /stockapp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TopSwagCode/AspNetCore.SignalR/a08ae6c74627b8fb85e4911a34f0d12bc8b66625/stockapp.gif -------------------------------------------------------------------------------- /wwwroot/assets/topswagcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TopSwagCode/AspNetCore.SignalR/a08ae6c74627b8fb85e4911a34f0d12bc8b66625/wwwroot/assets/topswagcode.png -------------------------------------------------------------------------------- /wwwroot/chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TopSwagCode - SignalR Chat 7 | 8 | 9 |
10 | 11 |
12 | 13 | 14 |
15 | 16 |

17 | 18 | 19 | 20 |

21 |

22 |

    23 |
  • Hi and welcome to TopSwagCode Chat.
  • 24 |
  • If no other users online try opening a second tab and chat with yourself :D
  • 25 |
26 |

27 |
28 |
29 |

TopSwagCode - SignalR Chat

30 |
31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /wwwroot/graph/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TopSwagCode - SignalR Graph 7 | 8 | 9 | 10 |
11 | 12 | 37 |
38 |
39 |

TopSwagCode - SignalR Graph

40 |
41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TopSwagCode - SignalR Samples 7 | 8 | 9 | 10 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /wwwroot/js/chat-app.js: -------------------------------------------------------------------------------- 1 | const connection = new signalR.HubConnectionBuilder() 2 | .withUrl("http://localhost:51133/chatHub") 3 | .build(); 4 | 5 | connection.on("ReceiveMessage", (user, message) => { 6 | const encodedMsg = user + " says: " + message; 7 | const li = document.createElement("li"); 8 | li.textContent = encodedMsg; 9 | document.getElementById("messagesList").appendChild(li); 10 | }); 11 | 12 | document.getElementById("sendButton").addEventListener("click", event => { 13 | const user = document.getElementById("userInput").value; 14 | const message = document.getElementById("messageInput").value; 15 | connection.invoke("SendMessage", user, message).catch(err => console.error(err)); 16 | event.preventDefault(); 17 | document.getElementById("messageInput").value = ""; 18 | }); 19 | 20 | connection.start().catch(err => console.error(err)); -------------------------------------------------------------------------------- /wwwroot/js/graph-app.js: -------------------------------------------------------------------------------- 1 | const connection = new signalR.HubConnectionBuilder() 2 | .withUrl("http://localhost:51133/graphHub") 3 | .build(); 4 | 5 | connection.on("LogWork", (work) => { 6 | console.log(work); 7 | myData.push(work); 8 | if (myData.length > 50) { 9 | myData.shift(); 10 | } 11 | 12 | myChart.update(); 13 | }); 14 | 15 | connection.start().catch(err => console.error(err)); 16 | 17 | connection.onclose(function () { 18 | console.log("closing connection"); 19 | timeoutConnection(); 20 | }); 21 | 22 | function timeoutConnection(){ 23 | setTimeout(function(){ startConnection(); }, 3000); 24 | } 25 | 26 | function startConnection(){ 27 | connection.start().catch(err => timeoutConnection()); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /wwwroot/js/processing-app.js: -------------------------------------------------------------------------------- 1 | const connection = new signalR.HubConnectionBuilder() 2 | .withUrl("http://localhost:51133/processHub") 3 | .build(); 4 | 5 | connection.on("process", (progressValue) => { 6 | document.getElementById("progressBar").value = progressValue 7 | }); 8 | 9 | connection.on("processDone", (progressResult) => { 10 | toggleProggress(); 11 | toggleDownload(progressResult); 12 | }); 13 | 14 | document.addEventListener("DOMContentLoaded", function(event) { 15 | document.querySelector('button').addEventListener("click", function(event){ 16 | connection.invoke("StartProcessing").catch(err => console.error(err)); 17 | toggleButton(); 18 | toggleProggress(); 19 | }); 20 | }); 21 | 22 | connection.start().catch(err => console.error(err)); 23 | 24 | function toggleProggress() { 25 | var x = document.getElementById("progressBar"); 26 | if (x.style.display === "none") { 27 | x.style.display = "block"; 28 | } else { 29 | x.style.display = "none"; 30 | } 31 | } 32 | 33 | function toggleButton() { 34 | var x = document.getElementById("processButton"); 35 | if (x.style.display === "none") { 36 | x.style.display = "block"; 37 | } else { 38 | x.style.display = "none"; 39 | } 40 | } 41 | 42 | function toggleDownload(progressResult) { 43 | var x = document.getElementById("download"); 44 | x.href = progressResult; 45 | if (x.style.display === "none") { 46 | x.style.display = "block"; 47 | } else { 48 | x.style.display = "none"; 49 | } 50 | } -------------------------------------------------------------------------------- /wwwroot/js/signalr.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root,factory){if(typeof exports==="object"&&typeof module==="object")module.exports=factory();else if(typeof define==="function"&&define.amd)define([],factory);else if(typeof exports==="object")exports["signalR"]=factory();else root["signalR"]=factory()})(window,function(){return function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{enumerable:true,get:getter})}};__webpack_require__.r=function(exports){if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(exports,"__esModule",{value:true})};__webpack_require__.t=function(value,mode){if(mode&1)value=__webpack_require__(value);if(mode&8)return value;if(mode&4&&typeof value==="object"&&value&&value.__esModule)return value;var ns=Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns,"default",{enumerable:true,value:value});if(mode&2&&typeof value!="string")for(var key in value)__webpack_require__.d(ns,key,function(key){return value[key]}.bind(null,key));return ns};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module["default"]}:function getModuleExports(){return module};__webpack_require__.d(getter,"a",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p="";return __webpack_require__(__webpack_require__.s=0)}([function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);var es6_promise_dist_es6_promise_auto_js__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(1);var es6_promise_dist_es6_promise_auto_js__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(es6_promise_dist_es6_promise_auto_js__WEBPACK_IMPORTED_MODULE_0__);var _index__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(3);__webpack_require__.d(__webpack_exports__,"VERSION",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["VERSION"]});__webpack_require__.d(__webpack_exports__,"AbortError",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["AbortError"]});__webpack_require__.d(__webpack_exports__,"HttpError",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HttpError"]});__webpack_require__.d(__webpack_exports__,"TimeoutError",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["TimeoutError"]});__webpack_require__.d(__webpack_exports__,"HttpClient",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HttpClient"]});__webpack_require__.d(__webpack_exports__,"HttpResponse",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HttpResponse"]});__webpack_require__.d(__webpack_exports__,"DefaultHttpClient",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["DefaultHttpClient"]});__webpack_require__.d(__webpack_exports__,"HubConnection",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HubConnection"]});__webpack_require__.d(__webpack_exports__,"HubConnectionState",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HubConnectionState"]});__webpack_require__.d(__webpack_exports__,"HubConnectionBuilder",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HubConnectionBuilder"]});__webpack_require__.d(__webpack_exports__,"MessageType",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["MessageType"]});__webpack_require__.d(__webpack_exports__,"LogLevel",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["LogLevel"]});__webpack_require__.d(__webpack_exports__,"HttpTransportType",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["HttpTransportType"]});__webpack_require__.d(__webpack_exports__,"TransferFormat",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["TransferFormat"]});__webpack_require__.d(__webpack_exports__,"NullLogger",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["NullLogger"]});__webpack_require__.d(__webpack_exports__,"JsonHubProtocol",function(){return _index__WEBPACK_IMPORTED_MODULE_1__["JsonHubProtocol"]});if(!Uint8Array.prototype.indexOf){Object.defineProperty(Uint8Array.prototype,"indexOf",{value:Array.prototype.indexOf,writable:true})}if(!Uint8Array.prototype.slice){Object.defineProperty(Uint8Array.prototype,"slice",{value:Array.prototype.slice,writable:true})}if(!Uint8Array.prototype.forEach){Object.defineProperty(Uint8Array.prototype,"forEach",{value:Array.prototype.forEach,writable:true})}},function(module,exports,__webpack_require__){(function(global){var require; 2 | /*! 3 | * @overview es6-promise - a tiny implementation of Promises/A+. 4 | * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 5 | * @license Licensed under MIT license 6 | * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 7 | * @version v4.2.2+97478eb6 8 | */ 9 | /*! 10 | * @overview es6-promise - a tiny implementation of Promises/A+. 11 | * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 12 | * @license Licensed under MIT license 13 | * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 14 | * @version v4.2.2+97478eb6 15 | */ 16 | (function(global,factory){true?module.exports=factory():undefined})(this,function(){"use strict";function objectOrFunction(x){var type=typeof x;return x!==null&&(type==="object"||type==="function")}function isFunction(x){return typeof x==="function"}var _isArray=void 0;if(Array.isArray){_isArray=Array.isArray}else{_isArray=function(x){return Object.prototype.toString.call(x)==="[object Array]"}}var isArray=_isArray;var len=0;var vertxNext=void 0;var customSchedulerFn=void 0;var asap=function asap(callback,arg){queue[len]=callback;queue[len+1]=arg;len+=2;if(len===2){if(customSchedulerFn){customSchedulerFn(flush)}else{scheduleFlush()}}};function setScheduler(scheduleFn){customSchedulerFn=scheduleFn}function setAsap(asapFn){asap=asapFn}var browserWindow=typeof window!=="undefined"?window:undefined;var browserGlobal=browserWindow||{};var BrowserMutationObserver=browserGlobal.MutationObserver||browserGlobal.WebKitMutationObserver;var isNode=typeof self==="undefined"&&typeof process!=="undefined"&&{}.toString.call(process)==="[object process]";var isWorker=typeof Uint8ClampedArray!=="undefined"&&typeof importScripts!=="undefined"&&typeof MessageChannel!=="undefined";function useNextTick(){return function(){return process.nextTick(flush)}}function useVertxTimer(){if(typeof vertxNext!=="undefined"){return function(){vertxNext(flush)}}return useSetTimeout()}function useMutationObserver(){var iterations=0;var observer=new BrowserMutationObserver(flush);var node=document.createTextNode("");observer.observe(node,{characterData:true});return function(){node.data=iterations=++iterations%2}}function useMessageChannel(){var channel=new MessageChannel;channel.port1.onmessage=flush;return function(){return channel.port2.postMessage(0)}}function useSetTimeout(){var globalSetTimeout=setTimeout;return function(){return globalSetTimeout(flush,1)}}var queue=new Array(1e3);function flush(){for(var i=0;i=200&&xhr.status<300){resolve(new _HttpClient__WEBPACK_IMPORTED_MODULE_1__["HttpResponse"](xhr.status,xhr.statusText,xhr.response||xhr.responseText))}else{reject(new _Errors__WEBPACK_IMPORTED_MODULE_0__["HttpError"](xhr.statusText,xhr.status))}};xhr.onerror=function(){_this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_2__["LogLevel"].Warning,"Error from HTTP request. "+xhr.status+": "+xhr.statusText+".");reject(new _Errors__WEBPACK_IMPORTED_MODULE_0__["HttpError"](xhr.statusText,xhr.status))};xhr.ontimeout=function(){_this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_2__["LogLevel"].Warning,"Timeout from HTTP request.");reject(new _Errors__WEBPACK_IMPORTED_MODULE_0__["TimeoutError"])};xhr.send(request.content||"")})};return XhrHttpClient}(_HttpClient__WEBPACK_IMPORTED_MODULE_1__["HttpClient"])},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"LogLevel",function(){return LogLevel});var LogLevel;(function(LogLevel){LogLevel[LogLevel["Trace"]=0]="Trace";LogLevel[LogLevel["Debug"]=1]="Debug";LogLevel[LogLevel["Information"]=2]="Information";LogLevel[LogLevel["Warning"]=3]="Warning";LogLevel[LogLevel["Error"]=4]="Error";LogLevel[LogLevel["Critical"]=5]="Critical";LogLevel[LogLevel["None"]=6]="None"})(LogLevel||(LogLevel={}))},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"HubConnectionState",function(){return HubConnectionState});__webpack_require__.d(__webpack_exports__,"HubConnection",function(){return HubConnection});var _HandshakeProtocol__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(11);var _IHubProtocol__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(15);var _ILogger__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(9);var _Utils__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(13);var __awaiter=undefined&&undefined.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator["throw"](value))}catch(e){reject(e)}}function step(result){result.done?resolve(result.value):new P(function(resolve){resolve(result.value)}).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};var __generator=undefined&&undefined.__generator||function(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},f,y,t,g;return g={next:verb(0),throw:verb(1),return:verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]responseLength?binaryData.slice(responseLength).buffer:null}else{var textData=data;var separatorIndex=textData.indexOf(_TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__["TextMessageFormat"].RecordSeparator);if(separatorIndex===-1){throw new Error("Message is incomplete.")}var responseLength=separatorIndex+1;messageData=textData.substring(0,responseLength);remainingData=textData.length>responseLength?textData.substring(responseLength):null}var messages=_TextMessageFormat__WEBPACK_IMPORTED_MODULE_0__["TextMessageFormat"].parse(messageData);var response=JSON.parse(messages[0]);if(response.type){throw new Error("Expected a handshake response from the server.")}responseMessage=response;return[remainingData,responseMessage]};return HandshakeProtocol}()},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"TextMessageFormat",function(){return TextMessageFormat});var TextMessageFormat=function(){function TextMessageFormat(){}TextMessageFormat.write=function(output){return""+output+TextMessageFormat.RecordSeparator};TextMessageFormat.parse=function(input){if(input[input.length-1]!==TextMessageFormat.RecordSeparator){throw new Error("Message is incomplete.")}var messages=input.split(TextMessageFormat.RecordSeparator);messages.pop();return messages};TextMessageFormat.RecordSeparatorCode=30;TextMessageFormat.RecordSeparator=String.fromCharCode(TextMessageFormat.RecordSeparatorCode);return TextMessageFormat}()},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"Arg",function(){return Arg});__webpack_require__.d(__webpack_exports__,"getDataDetail",function(){return getDataDetail});__webpack_require__.d(__webpack_exports__,"formatArrayBuffer",function(){return formatArrayBuffer});__webpack_require__.d(__webpack_exports__,"isArrayBuffer",function(){return isArrayBuffer});__webpack_require__.d(__webpack_exports__,"sendMessage",function(){return sendMessage});__webpack_require__.d(__webpack_exports__,"createLogger",function(){return createLogger});__webpack_require__.d(__webpack_exports__,"Subject",function(){return Subject});__webpack_require__.d(__webpack_exports__,"SubjectSubscription",function(){return SubjectSubscription});__webpack_require__.d(__webpack_exports__,"ConsoleLogger",function(){return ConsoleLogger});var _ILogger__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(9);var _Loggers__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(14);var __awaiter=undefined&&undefined.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator["throw"](value))}catch(e){reject(e)}}function step(result){result.done?resolve(result.value):new P(function(resolve){resolve(result.value)}).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};var __generator=undefined&&undefined.__generator||function(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},f,y,t,g;return g={next:verb(0),throw:verb(1),return:verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]-1){this.subject.observers.splice(index,1)}if(this.subject.observers.length===0&&this.subject.cancelCallback){this.subject.cancelCallback().catch(function(_){})}};return SubjectSubscription}();var ConsoleLogger=function(){function ConsoleLogger(minimumLogLevel){this.minimumLogLevel=minimumLogLevel}ConsoleLogger.prototype.log=function(logLevel,message){if(logLevel>=this.minimumLogLevel){switch(logLevel){case _ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"].Critical:case _ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"].Error:console.error("["+(new Date).toISOString()+"] "+_ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"][logLevel]+": "+message);break;case _ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"].Warning:console.warn("["+(new Date).toISOString()+"] "+_ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"][logLevel]+": "+message);break;case _ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"].Information:console.info("["+(new Date).toISOString()+"] "+_ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"][logLevel]+": "+message);break;default:console.log("["+(new Date).toISOString()+"] "+_ILogger__WEBPACK_IMPORTED_MODULE_0__["LogLevel"][logLevel]+": "+message);break}}};return ConsoleLogger}()},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"NullLogger",function(){return NullLogger});var NullLogger=function(){function NullLogger(){}NullLogger.prototype.log=function(_logLevel,_message){};NullLogger.instance=new NullLogger;return NullLogger}()},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"MessageType",function(){return MessageType});var MessageType;(function(MessageType){MessageType[MessageType["Invocation"]=1]="Invocation";MessageType[MessageType["StreamItem"]=2]="StreamItem";MessageType[MessageType["Completion"]=3]="Completion";MessageType[MessageType["StreamInvocation"]=4]="StreamInvocation";MessageType[MessageType["CancelInvocation"]=5]="CancelInvocation";MessageType[MessageType["Ping"]=6]="Ping";MessageType[MessageType["Close"]=7]="Close"})(MessageType||(MessageType={}))},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"HubConnectionBuilder",function(){return HubConnectionBuilder});var _HttpConnection__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(17);var _HubConnection__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(10);var _JsonHubProtocol__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(23);var _Loggers__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(14);var _Utils__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(13);var HubConnectionBuilder=function(){function HubConnectionBuilder(){}HubConnectionBuilder.prototype.configureLogging=function(logging){_Utils__WEBPACK_IMPORTED_MODULE_4__["Arg"].isRequired(logging,"logging");if(isLogger(logging)){this.logger=logging}else{this.logger=new _Utils__WEBPACK_IMPORTED_MODULE_4__["ConsoleLogger"](logging)}return this};HubConnectionBuilder.prototype.withUrl=function(url,transportTypeOrOptions){_Utils__WEBPACK_IMPORTED_MODULE_4__["Arg"].isRequired(url,"url");this.url=url;if(typeof transportTypeOrOptions==="object"){this.httpConnectionOptions=transportTypeOrOptions}else{this.httpConnectionOptions={transport:transportTypeOrOptions}}return this};HubConnectionBuilder.prototype.withHubProtocol=function(protocol){_Utils__WEBPACK_IMPORTED_MODULE_4__["Arg"].isRequired(protocol,"protocol");this.protocol=protocol;return this};HubConnectionBuilder.prototype.build=function(){var httpConnectionOptions=this.httpConnectionOptions||{};if(httpConnectionOptions.logger===undefined){httpConnectionOptions.logger=this.logger}if(!this.url){throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.")}var connection=new _HttpConnection__WEBPACK_IMPORTED_MODULE_0__["HttpConnection"](this.url,httpConnectionOptions);return _HubConnection__WEBPACK_IMPORTED_MODULE_1__["HubConnection"].create(connection,this.logger||_Loggers__WEBPACK_IMPORTED_MODULE_3__["NullLogger"].instance,this.protocol||new _JsonHubProtocol__WEBPACK_IMPORTED_MODULE_2__["JsonHubProtocol"])};return HubConnectionBuilder}();function isLogger(logger){return logger.log!==undefined}},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"HttpConnection",function(){return HttpConnection});var _DefaultHttpClient__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(6);var _ILogger__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(9);var _ITransport__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(18);var _LongPollingTransport__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(19);var _ServerSentEventsTransport__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(21);var _Utils__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(13);var _WebSocketTransport__WEBPACK_IMPORTED_MODULE_6__=__webpack_require__(22);var __awaiter=undefined&&undefined.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator["throw"](value))}catch(e){reject(e)}}function step(result){result.done?resolve(result.value):new P(function(resolve){resolve(result.value)}).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};var __generator=undefined&&undefined.__generator||function(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},f,y,t,g;return g={next:verb(0),throw:verb(1),return:verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]=0){if(transport===_ITransport__WEBPACK_IMPORTED_MODULE_2__["HttpTransportType"].WebSockets&&!this.options.WebSocket||transport===_ITransport__WEBPACK_IMPORTED_MODULE_2__["HttpTransportType"].ServerSentEvents&&!this.options.EventSource){this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Debug,"Skipping transport '"+_ITransport__WEBPACK_IMPORTED_MODULE_2__["HttpTransportType"][transport]+"' because it is not supported in your environment.'")}else{this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Debug,"Selecting transport '"+_ITransport__WEBPACK_IMPORTED_MODULE_2__["HttpTransportType"][transport]+"'.");return transport}}else{this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Debug,"Skipping transport '"+_ITransport__WEBPACK_IMPORTED_MODULE_2__["HttpTransportType"][transport]+"' because it does not support the requested transfer format '"+_ITransport__WEBPACK_IMPORTED_MODULE_2__["TransferFormat"][requestedTransferFormat]+"'.")}}else{this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Debug,"Skipping transport '"+_ITransport__WEBPACK_IMPORTED_MODULE_2__["HttpTransportType"][transport]+"' because it was disabled by the client.")}}return null};HttpConnection.prototype.isITransport=function(transport){return transport&&typeof transport==="object"&&"connect"in transport};HttpConnection.prototype.changeState=function(from,to){if(this.connectionState===from){this.connectionState=to;return true}return false};HttpConnection.prototype.stopConnection=function(error){this.transport=undefined;error=this.stopError||error;if(error){this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Error,"Connection disconnected with error '"+error+"'.")}else{this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Information,"Connection disconnected.")}this.connectionState=2;if(this.onclose){this.onclose(error)}};HttpConnection.prototype.resolveUrl=function(url){if(url.lastIndexOf("https://",0)===0||url.lastIndexOf("http://",0)===0){return url}if(typeof window==="undefined"||!window||!window.document){throw new Error("Cannot resolve '"+url+"'.")}var aTag=window.document.createElement("a");aTag.href=url;this.logger.log(_ILogger__WEBPACK_IMPORTED_MODULE_1__["LogLevel"].Information,"Normalizing '"+url+"' to '"+aTag.href+"'.");return aTag.href};HttpConnection.prototype.resolveNegotiateUrl=function(url){var index=url.indexOf("?");var negotiateUrl=url.substring(0,index===-1?url.length:index);if(negotiateUrl[negotiateUrl.length-1]!=="/"){negotiateUrl+="/"}negotiateUrl+="negotiate";negotiateUrl+=index===-1?"":url.substring(index);return negotiateUrl};return HttpConnection}();function transportMatches(requestedTransport,actualTransport){return!requestedTransport||(actualTransport&requestedTransport)!==0}},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"HttpTransportType",function(){return HttpTransportType});__webpack_require__.d(__webpack_exports__,"TransferFormat",function(){return TransferFormat});var HttpTransportType;(function(HttpTransportType){HttpTransportType[HttpTransportType["None"]=0]="None";HttpTransportType[HttpTransportType["WebSockets"]=1]="WebSockets";HttpTransportType[HttpTransportType["ServerSentEvents"]=2]="ServerSentEvents";HttpTransportType[HttpTransportType["LongPolling"]=4]="LongPolling"})(HttpTransportType||(HttpTransportType={}));var TransferFormat;(function(TransferFormat){TransferFormat[TransferFormat["Text"]=1]="Text";TransferFormat[TransferFormat["Binary"]=2]="Binary"})(TransferFormat||(TransferFormat={}))},function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"LongPollingTransport",function(){return LongPollingTransport});var _AbortController__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(20);var _Errors__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(4);var _ILogger__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(9);var _ITransport__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(18);var _Utils__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(13);var __awaiter=undefined&&undefined.__awaiter||function(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator["throw"](value))}catch(e){reject(e)}}function step(result){result.done?resolve(result.value):new P(function(resolve){resolve(result.value)}).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})};var __generator=undefined&&undefined.__generator||function(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},f,y,t,g;return g={next:verb(0),throw:verb(1),return:verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1] { 6 | var stocks = JSON.parse(stocksJson); 7 | stocks.forEach(stock => { 8 | updateStock(stock); 9 | }); 10 | 11 | }); 12 | 13 | connection.start().catch(err => console.error(err)); 14 | 15 | connection.onclose(function () { 16 | timeoutConnection(); 17 | }); 18 | 19 | function timeoutConnection(){ 20 | setTimeout(function(){ startConnection(); }, 3000); 21 | } 22 | 23 | function startConnection(){ 24 | connection.start().catch(err => timeoutConnection()); 25 | } 26 | 27 | function updateStock(stock){ 28 | var stockElement = document.getElementById(stock.symbol); 29 | if(stockElement){ 30 | stockElement.cells[0].innerHTML = stock.symbol; 31 | stockElement.cells[1].innerHTML = stock.bid; 32 | stockElement.cells[2].innerHTML = stock.ask; 33 | stockElement.style.backgroundColor = "yellow"; 34 | 35 | setTimeout(function(){ UpdateBackgroundColor(stockElement); }, 1500); 36 | } 37 | else{ 38 | var table = document.getElementById("stocksTable"); 39 | var row = table.insertRow(1); 40 | row.id = stock.symbol; 41 | var symbolCell = row.insertCell(0); 42 | symbolCell.innerHTML = stock.symbol; 43 | 44 | var bidCell = row.insertCell(1); 45 | bidCell.innerHTML = stock.bid; 46 | 47 | var askCell = row.insertCell(2); 48 | askCell.innerHTML = stock.ask; 49 | } 50 | } 51 | 52 | function UpdateBackgroundColor(element){ 53 | element.style.backgroundColor = "white"; 54 | } 55 | -------------------------------------------------------------------------------- /wwwroot/processing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TopSwagCode - SignalR Processing 7 | 8 | 9 |
10 | 11 |
12 | 13 | 14 |
15 | 16 |

17 | 18 |

19 |

20 | 21 |

22 |

23 | 24 |

25 |
26 |
27 |

TopSwagCode - SignalR Processing

28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /wwwroot/stock/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TopSwagCode - SignalR Stocks 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
SymbolBidAsk
17 | 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------