Page 60 - MSDN Magazine, April 2018
P. 60

The JavaScript hub connection object must then be opened up via the start method. You can use JavaScript promises—specifically the then method—or async/await in TypeScript to perform sub- sequent actions such as initializing some user interface. A SignalR connection is uniquely identified by a string ID.
It’s important to notice that ASP.NET Core SignalR no longer supports automatic reconnect if the transport connection or the server fails. In older versions, in case of server failure the client attempts to re-establish a connection according to a scheduling algorithm and, if successful, it reopens a connection with the same ID. In SignalR Core if the connection drops the client can only start it again via the method start and this results in a different connec- tion instance over a different connection ID.
The Client Callback API
Another fundamental segment of JavaScript code you need is the JavaScript that will be called back by the hub to refresh the inter- face and reflect on the client that progress is being made on the server. The way you write this code is a bit different in ASP.NET Core SignalR from what it was in older versions, but the intent is exactly the same. In our example, we have three methods that could be called back from the server: initProgressBar, updateProgress- Bar and clearProgressBar. Needless to say, names and signatures
are arbitrary. Here’s a sample implementation:
progressConnection.on("initProgressBar", () => { setProgress(0);
$("#notification").show();
});
progressConnection.on("updateProgressBar", (perc) => {
setProgress(perc); });
progressConnection.on("clearProgressBar", () => { setProgress(100);
$("#notification").hide();
});
For example, when the initProgressBar method is called back from the server the helper setProgress JavaScript function will configure the progress bar (the demo uses a Bootstrap progress bar component) and show it. Note that the jQuery library is used in the code but only to update the UI. As mentioned, the client SignalR Core library is no longer a jQuery plug-in. Put another way, if your UI is based on, say, Angular then you may not need to use jQuery at all.
Server-Side Events
The missing piece is the part of the solution that decides when it’s about time to invoke a client function. There are two main scenar- ios. One is when the client invokes a server action through a Web API or a controller endpoint. The other is when the client directly invokes the hub. In the end, it’s all about where you code the task that calls the client back.
In the canonical chat example, it all happens within the hub: performance of any required logic and dispatch of messages to the appropriate connection. Monitoring a remote task is a dif- ferent thing. It assumes there’s some business process running in the background that notifies its progress in some way. Technical- ly, you might have this process coded in the hub and set up from there a conversation with the client UI. Or you can have the pro- cess triggered by a controller (API) and use the hub only as a way
to pass events to the client. Even more realistically than shown in the example, you have the process coded in a layer below the level of controllers.
In a nutshell, you define the hub class and make it available wherever you can decide when and if to invoke client functions. The interesting thing is what’s required to inject the hub instance into a controller or another business class. The demo injects the hub in a controller but it would do exactly the same for another deeper-level class. The sample TaskController is invoked via JavaScript directly from the client to trigger the remote task whose progresses will then move the progress bar:
public class TaskController : Controller {
private readonly IHubContext<ProgressHub> _progressHubContext;
public TaskController(IHubContext<ProgressHub> progressHubContext) {
_progressHubContext = progressHubContext;
}
public IActionResult Lengthy() {
// Perform the task and call back }
You inject a hub in a controller or in any other class via the IHubContext<THub> interface. The IHubContext interface wraps up the hub instance but doesn’t give you direct access to it. From there, you can dispatch messages back to the UI but you can’t access, for example, the connection ID. Let’s say the remote task is performed in the Lengthy method and it’s from there you want to update the client progress bar:
progressHubContext
.Clients
.Client(connId) .InvokeAsync("updateProgressBar", 45);
The connection ID can be retrieved from within the hub class but not from within a generic hub context as in this example. Hence, the simplest way is for the client method to pass the connection string when it starts the remote task:
public void Lengthy([Bind(Prefix="id")] string connId) { ... }
In the end, the controller class receives the SignalR connection ID, is injected the hub context and acts via the context calling meth- ods through a generic non-typed API—the InvokeAsync method. Used in this way, there’s no need to have methods in the hub class! If you find it surprising, well, take a look at the code at bit.ly/2DWd8SV.
Wrapping Up
This article discussed using ASP.NET Core SignalR in the context of a Web application to monitor a remote task. The hub is nearly empty as all the notification logic is built into the controller and orches- trated via the hub context injected via DI. This is just the starting point of a longer tour of ASP.NET Core SignalR. Next up, I’ll delve deeperintotheinfrastructureandexploretypedhubs,aswell. n
Dino Esposito has authored more than 20 books and 1,000 articles in his 25-year career. Author of “The Sabbatical Break,” a theatrical-style show, Esposito is busy writing software for a greener world as the digital strategist at BaxEnergy. Follow him on Twitter: @despos.
thanks to the following Microsoft expert for reviewing this article: Andrew Stanton-Nurse
}
54 msdn magazine
Title/Slug Here


































































































   58   59   60   61   62