{"id":26796366,"url":"https://github.com/simonemoreware/learn_signalr","last_synced_at":"2025-03-29T18:18:26.924Z","repository":{"id":235188972,"uuid":"790217558","full_name":"SimoneMoreWare/Learn_SignalR","owner":"SimoneMoreWare","description":"SignalR Tutorial ","archived":false,"fork":false,"pushed_at":"2024-04-23T12:22:44.000Z","size":4172,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-23T16:23:23.002Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimoneMoreWare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-04-22T13:31:23.000Z","updated_at":"2024-04-23T12:22:48.000Z","dependencies_parsed_at":"2024-04-22T16:23:22.722Z","dependency_job_id":"4ff22093-1f16-4441-bbda-4e1b4607b1c2","html_url":"https://github.com/SimoneMoreWare/Learn_SignalR","commit_stats":null,"previous_names":["simonemoreware/learn_signalr"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimoneMoreWare%2FLearn_SignalR","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimoneMoreWare%2FLearn_SignalR/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimoneMoreWare%2FLearn_SignalR/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimoneMoreWare%2FLearn_SignalR/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimoneMoreWare","download_url":"https://codeload.github.com/SimoneMoreWare/Learn_SignalR/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246223306,"owners_count":20743168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-29T18:18:26.430Z","updated_at":"2025-03-29T18:18:26.911Z","avatar_url":"https://github.com/SimoneMoreWare.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Learn_SignalR\nSignalR Tutorial \n\n# Notes\n\n# Video Courses\n* https://www.youtube.com/watch?v=pl0OobPmWTk\n* https://www.youtube.com/watch?v=8c8dknlwrJ4\u0026list=PL_c9BZzLwBRKJugyyAdhBoAPRs1DdaS7n\u0026index=20\n* https://www.youtube.com/watch?v=RaXx_f3bIRU\u0026t=3114s + https://www.youtube.com/watch?v=-JzWg-Kwu7g\n\n# Topic\n* [Overview of ASP.NET Core SignalR](#Overview-of-ASP.NET-Core-SignalR)\n    * [What is SignalR?](#What-is-SignalR?)\n    * [Use Cases Of SignalR](#Use-Cases-Of-SignalR)\n    * [When Not to Use SignalR](#When-Not-to-Use-SignalR)\n    * [Web Monitoring Application](#WebMonitoringApplication)\n    * [Transports](#Transports)\n    * [Hubs](#Hubs)\n    * [Browsers that don't support ECMAScript 6 (ES6)](#Browsers-that-don't-support-ECMAScript-6-(ES6))\n    * [RoadMap](#RoadMap)\n* [SignalR Typical Flow](#SignalR-Typical-Flow)\n* [Best practices](#Best-practices)\n* [Sample](#Sample)\n    * [Step 1: Create SignalR Hub](#step-1-create-signalr-hub)\n    * [Step 2 and 6: Add methods to hub and SignalR Hub invokes method in client JS to notify clients](#step-2-and-6-add-methods-to-hub-and-signalr-hub-invokes-method-in-client-js-to-notify-clients)\n    * [Other steps](#Other-steps)\n* [Invoke vs Send](#InvokevsSend)      \n* [Repository](#Repository)\n* [Site](#Site)\n* [Exercises](#Exercises)\n* [Payment Courses](#Payment-Courses)\n\n# Overview of ASP.NET Core SignalR\n\n## What is SignalR?\n\nASP.NET Core SignalR is an open-source library that simplifies adding real-time web functionality to apps. Real-time web functionality enables server-side code to push content to clients instantly.\n\nGood candidates for SignalR:\n\n* Apps that require high frequency updates from the server. Examples are gaming, social networks, voting, auction, maps, and GPS apps.\n* Dashboards and monitoring apps. Examples include company dashboards, instant sales updates, or travel alerts.\n* Collaborative apps. Whiteboard apps and team meeting software are examples of collaborative apps.\n* Apps that require notifications. Social networks, email, chat, games, travel alerts, and many other apps use notifications.\n\nSignalR provides an API for creating server-to-client remote procedure calls ([RPC](https://wikipedia.org/wiki/Remote_procedure_call)). The RPCs invoke functions on clients from server-side .NET Core code. There are several [supported platforms](https://learn.microsoft.com/en-us/aspnet/core/signalr/supported-platforms?view=aspnetcore-8.0), each with their respective client SDK. Because of this, the programming language being invoked by the RPC call varies.\n\nThe impact of SignalR is not restricted to enhancing user experience. Additionally, it decreases server load time by staying away from unnecessary polling. This reduction in unnecessary network traffic and server load can result in more scalable applications that can support much more simultaneous connections without sacrificing performance. Reduced Network Traffic Compared to Polling or Constant Refreshes: Traditional content update methods including polling or periodic page refreshes consume network traffic and server load. SignalR performs all communications between server and client efficiently, sending only data when updates can be found. This dramatically decreases bandwidth use and server resources, leading to a far more scalable and performant application.\n\nReduced Network Traffic Compared to Polling or Constant Refreshes: Traditional content update methods including polling or periodic page refreshes consume network traffic and server load. SignalR performs all communications between server and client efficiently, sending only data when updates can be found. This dramatically decreases bandwidth use and server resources, leading to a far more scalable and performant application.\n\nHere are some features of SignalR for ASP.NET Core:\n\n* Handles connection management automatically.\n* Sends messages to all connected clients simultaneously. For example, a chat room.\n* Sends messages to specific clients or groups of clients.\n* Scales to handle increasing traffic.\n* [SignalR Hub Protocol](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md)\n\nThe source is hosted in a [SignalR repository on GitHub](https://github.com/dotnet/AspNetCore/tree/main/src/SignalR)\n\n## Use Cases Of SignalR\n\n### Chat Applications\n\nSignalR is a leader in chat application development with instant messaging capabilities. [4]\nIt allows rich messaging applications where users can create rooms or groups and get messages in real time without having to refresh their internet browser.\nThis is crucial for applications that need group chats, private messaging, and handling a high number of concurrent users.\n\n### Real-time Dashboards:\n\nSignalR’s real time data push capabilities are especially helpful for dashboards that show live data updates, like stock trading platforms, weather apps or sports scores.\nIt allows the server to push updates to the dashboard when new data becomes available, enabling users to constantly have the up to date info without refreshing manually.\nThis is crucial for decision making in dynamic environments where data changes rapidly.\n\n### Online Gaming:\n\nIn online gaming, SignalR can be used to map game state between players to ensure that all players see the same game world.\nIt enables the creation of real time, multiplayer games through rapid and secure server-client interaction.\nThis synchronization is crucial for competitive and cooperative gaming where latency or game state discrepancies can have a large effect on gameplay.\n\n### Collaborative Editing:\n\nSignalR supports the development of applications where several users can edit documents or projects at the same time.\nSignalR facilitates collaborative work by making changes made by one user visible to all other users working on the document at the same time.\nThis is especially crucial in academic, creative, and professional settings where teamwork and collaboration is crucial to productivity.\n\n## When Not to Use SignalR\n\nSignalR is only as durable as the underlying connection. If the connectivity of a client application is not reliable, SignalR may not be the optimal choice.\n\nAnother consideration is the scalability of SignalR. Depending on the number of concurrently connected clients, a resource conflict may occur on the web server when respective limits are reached. In situations like this, it may be necessary to deploy the application to a server farm and use a backplane. Implementing this approach independently can be complex.\n\n\n## Web Monitoring Application\n\nSuppose we want to create a web monitoring application that provides the user with a dashboard capable of displaying a series of information that updates over time.\n\nOne approach is to cyclically call an API at certain intervals (polling) to update the data on the dashboard. However, there is a problem: if there is no updated data, we are unnecessarily increasing network traffic with our requests. An alternative is the technique of long-polling: if the server has no data available, instead of sending an empty response, it can keep the request alive until something happens or a predetermined timeout is reached. If there is new data, the complete response reaches the client. A completely different approach is to reverse the roles: the backend contacts the clients when new data is available (push).\n\nRemember that HTML5 has standardized WebSocket, which is a configurable permanent bidirectional connection via a JavaScript interface in compatible browsers. Unfortunately, there must be full WebSocket support, both client-side (browsers) and server-side, to make it available. Therefore, we need to provide alternative mechanisms (fallbacks) to ensure that our application always works.\n\nMicrosoft released an open-source library called SignalR for ASP.NET in 2013, which was rewritten for ASP.NET Core in 2018. SignalR abstracts all communication mechanism details by choosing the best one available. The result is being able to write code as if we were always in push mode. With SignalR, the server can call a JavaScript method on all its connected clients or on a specific one.\n\n\n## Transports\nSignalR supports the following techniques for handling real-time communication (in order of graceful fallback):\n\n* [WebSockets](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-8.0)\n    - WebSocket is a bidirectional full-duplex communication protocol that allows interactive communication between clients and servers.\n    - With SignalR, WebSocket is the preferred transport method when available, as it offers optimal performance and reduced latency.\n    - WebSocket establishes a persistent connection between the client and the server, allowing data to be sent both from the client to the server and from the server to the client without waiting for an explicit request.\n- This protocol is supported by many modern browsers and web servers.\n* Server-Sent Events\n    - SSE is a mechanism that allows the server to send events to the browser asynchronously over a single HTTP connection.\n    - Unlike WebSocket, SSE only allows the server to send data to the client; the client cannot send data to the server using SSE.\n    - SignalR supports SSE as one of the alternative transport protocols when WebSocket is not available.\n    - SSE is supported by many modern browsers, but it may not be available on all servers.\n* Long Polling\n    - Long Polling is a technique that simulates bidirectional connection by emulating a persistent connection between client and server through a series of HTTP requests.\n    - When the client makes a request to the server, the server does not respond immediately. Instead, it keeps the connection open until it has data to send to the client or until a timeout expires.\n    - When the server has data to send, it responds to the client's request with the data, and the client immediately sends a new request to keep the connection open.\n    - Long Polling is a less efficient technique compared to WebSocket and SSE, as it requires more bandwidth and increases latency.\n    - However, Long Polling can be used as a fallback when WebSocket and SSE are not available.\n\nSignalR automatically chooses the best transport method that is within the capabilities of the server and client.\n\n## Hubs\n\nSignalR uses hubs to communicate between clients and servers.\n\nA hub is a high-level pipeline that allows a client and server to call methods on each other. SignalR handles the dispatching across machine boundaries automatically, allowing clients to call methods on the server and vice versa. You can pass strongly-typed parameters to methods, which enables model binding. SignalR provides two built-in hub protocols: a text protocol based on JSON and a binary protocol based on [MessagePack](https://msgpack.org/). MessagePack generally creates smaller messages compared to JSON. Older browsers must support [XHR level 2](https://caniuse.com/#feat=xhr2) to provide MessagePack protocol support.\n\nHubs call client-side code by sending messages that contain the name and parameters of the client-side method. Objects sent as method parameters are deserialized using the configured protocol. The client tries to match the name to a method in the client-side code. When the client finds a match, it calls the method and passes to it the deserialized parameter data.\n\nIn SignalR, a hub is a component that serves as a central point of contact for real-time communication between clients and servers. A hub is a fundamental concept in SignalR and is implemented as a server-side class that exposes methods that can be called by clients and can in turn send messages to clients.\n\nKey Features of a Hub:\n\n1. **Exposed Methods**: A hub defines a set of methods that can be invoked by clients to interact with the server. These methods can accept parameters and may return values or asynchronous tasks.\n\n2. **Bidirectional Communication**: Hubs enable bidirectional communication between clients and servers. This means that clients can call methods exposed by the hub on the server, and at the same time, the server can send messages to clients through the hub.\n\n3. **Automatic Connection Management**: SignalR automatically manages connection handling for hubs. This means that when a client connects or disconnects, SignalR handles the connection lifecycle automatically and manages connections transparently for the application.\n\n4. **Transport Protocol Abstraction**: Hubs provide an abstraction over the various transport protocols supported by SignalR (such as WebSocket, SSE, and Long Polling), allowing developers to write server-side code without having to worry about the details of the underlying transport protocol.\n\n### Example Hub Definition:\n\n```csharp\nusing Microsoft.AspNetCore.SignalR;\nusing System.Threading.Tasks;\n\npublic class ChatHub : Hub\n{\n    public async Task SendMessage(string user, string message)\n    {\n        // Send the message to all clients\n        await Clients.All.SendAsync(\"ReceiveMessage\", user, message);\n    }\n}\n```\n\n![imgHub](https://github.com/SimoneMoreWare/Learn_SignalR/blob/main/img/hub.png)\n\n## Browsers that don't support ECMAScript 6 (ES6)\n\nSignalR targets ES6. For browsers that don't support ES6, transpile the library to ES5. For more information, see [Getting Started with ES6 – Transpiling ES6 to ES5 with Traceur and Babel](https://weblogs.asp.net/dwahlin/getting-started-with-es6-%E2%80%93-transpiling-es6-to-es5).\n\n## Additional resources\n* [Introduction to ASP.NET Core SignalR](https://learn.microsoft.com/en-us/training/modules/aspnet-core-signalr)\n* [Get started with SignalR for ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-8.0)\n* [Supported Platforms](https://learn.microsoft.com/en-us/aspnet/core/signalr/supported-platforms?view=aspnetcore-8.0)\n* [Hubs](https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-8.0)\n* [JavaScript client](https://learn.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-8.0)\n* [Browsers that don't support ECMAScript 6 (ES6)](https://learn.microsoft.com/en-us/aspnet/core/signalr/supported-platforms?view=aspnetcore-8.0#es6)\n\n## RoadMap\nhttps://learn.microsoft.com/it-it/aspnet/signalr/overview/getting-started/real-time-web-applications-with-signalr\n\n# SignalR Typical Flow\n\n1. Create SignalR Hub\n2. Add methods to hub\n3. add client side signalR\n4. connect to signalR hub from client js\n5. Call signalR hub method\n6. SignalR Hub invokes method in client JS to notify clients\n7. Client receives update from SignalR hub and performs action\n\n# Best practices\n\n* Minimize Message Size:\n    * Keep the data payloads as small as possible. This might involve sending only the necessary data or changes rather than full objects. For example, if you’re updating a user’s status, send only the status change rather than the entire user object: await Clients.All.SendAsync(\"UpdateStatus\", userId, newStatus);\n* Reduce Frequency of Messages\n    *   Implement mechanisms to throttle the number of messages sent over a period, especially in scenarios with rapid state changes. Consider a scenario where you’re tracking mouse movements in a collaborative drawing app. Instead of sending updates for every pixel change, you could send updates at regular intervals\n* Reconnecting Clients: Implement client-side logic to automatically reconnect in case of disconnection.\n``` \nconnection.onclose(async () =\u003e {\n    await start();\n});\n\nasync function start() {\n    try {\n        await connection.start();\n        console.log(\"SignalR Connected.\");\n    } catch (err) {\n        console.log(err);\n        setTimeout(start, 5000);\n    }\n}\n\nstart();\n```\n*  Authentication:\n    *  SignalR can use ASP.NET Core’s authentication system. Ensure that your hub methods are accessible only to authenticated users by applying the [Authorize] attribute.\n*  Authorization:\n    *  For more granular control, you can implement custom authorization policies based on user roles or claims.\n*  Logging:\n    *  Implement logging to monitor connection density, message throughput, and error rates. ASP.NET Core’s built-in logging providers can be configured in Startup.cs.\n*  Scale-Out:\n    *  For applications needing to support thousands of concurrent connections, consider using Azure SignalR Service or similar scale-out mechanisms. To use Azure SignalR Service, add the service connection string to your appsettings.json and modify the Startup.cs to include: services.AddSignalR().AddAzureSignalR(connectionString);\n \n# Sample\n\n## Step 1: Create SignalR Hub\n\nCreate a new ASP.NET core MVC .net 8 project in Visual Studio 2022. You should configure the project with \"individual account\" in \"authentication type\". \n\nAdd this sample to a GitHub repository. \n\nNow, we will create the hub. Add the new folder in the project called \"Hubs\". In this folder you should create a new class file called \"UserHub.cs\". You remember that you include \"using Microsoft.AspNetCore.SignalR;\"+\n\nAt the moment, you add signalR service in the program.cs file `builder.Services.AddSignalR();`. However, you map an endpoint for a SignalR hub `app.MapHub\u003cUserHub\u003e(\"/hubs/user\");`\n\nHere's a breakdown of each part:\n* app: Refers to the IApplicationBuilder object, which is used to configure the ASP.NET Core application during the startup phase.\n* MapHub\u003cUserHub\u003e(\"/hubs/user\"): This MapHub method is configuring the path (\"/hubs/user\") for your SignalR hub. The type UserHub specified within the angle brackets is the type of your hub, which should extend Hub provided by SignalR.\n* When a client connects to \"/hubs/user\", SignalR will automatically handle the communication between the client and the server using the UserHub hub. This is useful for achieving bidirectional real-time communication between the client and the server, such as implementing real-time chat or real-time updates of information displayed in the application.\n\n\n## Step 2 and 6: Add methods to hub and SignalR Hub invokes method in client JS to notify clients\n\n```\nusing Microsoft.AspNetCore.SignalR;\n\nnamespace SignlalRSample.Hubs\n{\n\tpublic class UserHub : Hub\n\t{\n\t\tpublic static int TotalViews { get; set; } = 0;\n\n\t\tpublic async Task NewWindowLoaded()\n\t\t{\n\t\t\tTotalViews++;\n\t\t\t//send update to all clients that total views have been updated\n\t\t\tawait Clients.All.SendAsync(\"updateTotalViews\", TotalViews);\n\t\t}\n}\n\n```\n\nThe responsibility of UserHub is to count the number of views on a web page.\n\n`using Microsoft.AspNetCore.SignalR;`\nThis line imports the Microsoft.AspNetCore.SignalR namespace, which contains classes and tools necessary for using SignalR within an ASP.NET Core application.\n\nUserHub Class Definition\n`public class UserHub : Hub`\nThe UserHub class is a class that extends Hub. This serves as the focal point for managing client connections and sending messages to clients.\n\nStatic Property TotalViews\n`public static int TotalViews { get; set; } = 0;`\nThis is a static property that tracks the total number of views. It is shared among all instances of the UserHub class.\n\n```\nMethod NewWindowLoaded()\npublic async Task NewWindowLoaded()\n{\n    TotalViews++;\n    //send update to all clients that total views have been updated\n    await Clients.All.SendAsync(\"updateTotalViews\", TotalViews);\n}\n```\nThis method is called when a new window is loaded (presumably on the client side). It increments the count of total views and then sends an update to all connected clients using the SendAsync method. The name of the method to be called on the client is \"updateTotalViews\", and the new value of TotalViews is passed as an argument.\n\n## Other steps\n\nNow, you should add a client-side library. At the moment, you should choose unpkg provider and @microsoft/signalr@latest library. Now, there is signalr.js in the wwwroot folder. You move the signalr.js file in the JS folder.\n\n```\n//create connection\nvar connectionUserCount = new signalR.HubConnectionBuilder().withUrl(\"/hubs/userCount\", signalR.HttpTransportType.WebSockets).build();\n\n//connect to methods that hub invokes aka receive notfications from hub\nconnectionUserCount.on(\"updateTotalViews\", (value) =\u003e {\n    var newCountSpan = document.getElementById(\"totalViewsCounter\");\n    newCountSpan.innerText = value.toString();\n});\n\nconnectionUserCount.on(\"updateTotalUsers\", (value) =\u003e {\n    var newCountSpan = document.getElementById(\"totalUsersCounter\");\n    newCountSpan.innerText = value.toString();\n});\n\n//invoke hub methods aka send notification to hub\nfunction newWindowLoadedOnClient() {\n    connectionUserCount.send(\"NewWindowLoaded\");\n}\n\n//start connection\nfunction fulfilled() {\n    //do something on start\n    console.log(\"Connection to User Hub Successful\");\n    newWindowLoadedOnClient();\n}\nfunction rejected() {\n    //rejected logs\n}\n\nconnectionUserCount.start().then(fulfilled, rejected);\n```\nThis JavaScript file, usersCount.js, handles the connection to the SignalR service within an ASP.NET Core MVC project. SignalR is a framework for building real-time web applications that enables bidirectional communication between client and server.\n\nHere's what happens step by step within this file:\n\n1. Creation of SignalR hub connection:\nAn object connectionUserCount is created using HubConnectionBuilder provided by SignalR. This object is configured with the URL of the SignalR hub (\"/hubs/userCount\").\n    * new signalR.HubConnectionBuilder(): This creates a new instance of HubConnectionBuilder, which is used to configure and build a SignalR hub connection.\n    * .withUrl(\"/hubs/userCount\", signalR.HttpTransportType.WebSockets): This method configures the URL for the hub connection and specifies the transport type to be used.\n    * \"/hubs/userCount\": This specifies the URL where the SignalR hub is hosted. In this case, it's assumed to be located at \"/hubs/userCount\".\n    * signalR.HttpTransportType.WebSockets: This parameter specifies the transport type to be used for the connection. In this case, it's configured to use WebSockets as the transport type.\n        * WebSockets is a communication protocol that provides full-duplex communication channels over a single TCP connection. It's commonly used for real-time web applications due to its low latency and efficient data exchange.\n        * .build(): This method finalizes the configuration and builds the hub connection object.\n3. Handling notifications from the server:\nA callback function on is defined to handle the \"updateTotalView\" event sent by the server. When the server sends this notification, the associated value is updated inside an HTML element with id \"totalViewsCounter\".\n4. Sending notifications to the server:\nA function newWindowLoadedOnClient is defined to send a notification to the server called \"NewWindowLoaded\" via the connectionUserCount connection. This function seems to be called when a new window is loaded in the client.\n5. Handling connection state:\nA function fulfilled is defined which is called when the connection to the SignalR hub is successfully established. Similarly, a function rejected is defined which should handle any connection errors. However, the rejected function appears to be empty, so it does nothing.\n6. Starting the connection:\nThe connection to the SignalR hub is started using the start() method. .then() is used to handle the result of starting the connection, so that if the connection succeeds, the fulfilled function is called, otherwise the rejected function is called.\n\n## Update number of user\n\n```\nusing Microsoft.AspNetCore.SignalR;\n\nnamespace SignlalRSample.Hubs\n{\n\tpublic class UserHub : Hub\n\t{\n\t\tpublic static int TotalViews { get; set; } = 0;\n\t\tpublic static int TotalUsers { get; set; } = 0;\n\n\t\tpublic async Task NewWindowLoaded()\n\t\t{\n\t\t\tTotalViews++;\n\t\t\t//send update to all clients that total views have been updated\n\t\t\tawait Clients.All.SendAsync(\"updateTotalViews\", TotalViews);\n\t\t}\n\n\t\tpublic override Task OnConnectedAsync()\n\t\t{\n\t\t\tTotalUsers++;\n\t\t\tClients.All.SendAsync(\"updateTotalUsers\", TotalViews).GetAwaiter().GetResult();\n\t\t\treturn base.OnConnectedAsync();\n\t\t}\n\n\t\tpublic override Task OnDisconnectedAsync(Exception? exception)\n\t\t{\n\t\t\tTotalUsers--;\n\t\t\tClients.All.SendAsync(\"updateTotalUsers\", TotalViews).GetAwaiter().GetResult();\n\t\t\treturn base.OnDisconnectedAsync(exception);\n\t\t}\n\n\n\t}\n}\n```\nExplanation of the Methods:\n\nOnConnectedAsync()\nThis method is automatically called when a client connects to the server via SignalR.\nIt increments the TotalUsers counter, presumably tracking the total number of connected users.\nThen, it sends a message to all connected clients using Clients.All.SendAsync(\"updateTotalUsers\", TotalUsers). This method asynchronously sends a message to all connected clients, which will call the JavaScript function updateTotalUsers on the client side with TotalUsers as an argument.\nFinally, it returns the execution to the base method base.OnConnectedAsync().\n\nOnDisconnectedAsync(Exception? exception)\nThis method is automatically called when a client disconnects from the SignalR server.\nIt decrements the TotalUsers counter.\nThen, it sends a message to all connected clients to update the user count, using Clients.All.SendAsync(\"updateTotalUsers\", TotalUsers).\nFinally, it returns the execution to the base method base.OnDisconnectedAsync(exception).\n\nAbout .GetAwaiter().GetResult():\nThe .GetAwaiter().GetResult() method is used to perform an asynchronous operation synchronously. In practice, when using .GetAwaiter().GetResult(), you are blocking the current thread until the asynchronous operation completes, either getting the result or handling any exceptions.\nIn the context of your OnConnectedAsync() and OnDisconnectedAsync() methods, these two methods are used after invoking SendAsync() to wait for the message to be sent to connected clients before proceeding with the rest of the code.\nHowever, using .GetAwaiter().GetResult() in an asynchronous environment can pose risks of thread blocking and potential performance issues, especially in high-concurrency scenarios. It's generally preferable to use the complete asynchronous pattern and avoid blocking the main thread. Instead of .GetAwaiter().GetResult(), you might consider using await in an asynchronous context.\n\n# Invoke vs Send\n\nInvoke:\nInvoke is a more generic method that allows the client to call methods defined on the server.\nIt can be used to invoke any method defined on the SignalR server side, including methods defined in SignalR hubs.\nWhen a client invokes a method on the server using Invoke, the server executes the specified method and can send a response to the client if necessary.\nWith invoke we want in general a result from server.\n\nSend:\nSend is specifically designed to send broadcast messages or specific messages to all connected clients or specific groups of clients.\nIt is used to send messages to all connected clients or a specific group of clients without the need to define methods on the server for each type of message.\nIt is commonly used to send general updates or notifications to all connected clients, such as in the case of status updates, chat notifications, or alerts.\n\nFor example, the difference between `connectionUserCount.send(\"NewWindowLoaded\");` and `    connectionUserCount.invoke(\"NewWindowLoaded\", \"Bhrugen\").then((value) =\u003e console.log(value))`.\n\n`connectionUserCount.send(\"NewWindowLoaded\");`\nWith this statement, you are sending a message \"NewWindowLoaded\" to the server without expecting a specific response. This is useful for sending notifications or updates to clients without requiring a response from the server.\n\n`connectionUserCount.invoke(\"NewWindowLoaded\", \"Bhrugen\").then((value) =\u003e console.log(value))`\nWith this statement, you are invoking the method \"NewWindowLoaded\" on the server and passing \"Bhrugen\" as a parameter. Additionally, you are waiting for a response from the server using .then((value) =\u003e console.log(value)). This means that once the server has processed the method and returned a result, the callback function will be called with the value returned by the server. This is useful when you need to get a specific response from the server after invoking a method.\n\n\n# Repository\n* https://github.com/dotnet/AspNetCore/tree/main/src/SignalR\n* https://github.com/bhrugen/SignalRSample\n\n# PDFs\n* [SignalR Basic Flow](https://github.com/SimoneMoreWare/Learn_SignalR/blob/main/pdf/SignalR%20Basic%20Flow.pdf)\n* [SignalR Slides](https://github.com/SimoneMoreWare/Learn_SignalR/blob/main/pdf/SignalR.pdf)\n\n# Site\n* https://dotnet.microsoft.com/en-us/apps/aspnet/signalr\n* https://learn.microsoft.com/en-us/azure/azure-signalr/\n* https://medium.com/@basuraratnayake/c-tutorial-signalr-b7a7b76901be\n\n# Exercises\n* https://www.sitepoint.com/build-real-time-signalr-dashboard-angularjs/\n* https://www.telerik.com/blogs/real-time-winui-dashboard-with-signalr-backend\n* https://medium.com/@ajith.ramawickrama/develop-a-real-time-dashboard-using-azure-cosmosdb-azure-functions-azure-signalr-services-and-ac670de580f4\n* https://blog.saverioriotto.it/blog/296/tutorial/creare-una-web-app-in-tempo-reale-con-blazor-e-signalr\n* https://www.youtube.com/watch?v=pvi_ZS_PrSc\u0026pp=ugMICgJpdBABGAHKBQdzaWduYWxy\n* https://www.youtube.com/watch?v=O7oaxFgNuYo\n\n# Payment Courses\n* https://www.udemy.com/course/signalr-mastery/?couponCode=LETSLEARNNOW\n* https://www.udemy.com/course/signalr-the-complete-guide/?couponCode=LETSLEARNNOW\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonemoreware%2Flearn_signalr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonemoreware%2Flearn_signalr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonemoreware%2Flearn_signalr/lists"}