I’m a little late getting the wrapup blog posts together for this week’s streams, so I figured I would just pull them all into one MEGA-UPDATE. It was a crazy week for me, with a LOT accomplished outside of the stream… I cleaned up my security mess with Amazon, and worked on some cool SignalR integration with our StreamTools project.
We started Tuesday with a quick summary of my interactions with Amazon. I still have not heard a full report from them, and I’m very annoyed at the ease at which they have taken a criminal break-in to my account. I fear that they really don’t have protocols or steps that they take to protect our accounts. I will not be leaving my credit card on Amazon’s systems any longer, because I do not trust their security… at all.
I highlighted that my recording with the .NET Rocks podcast was available, and I talk with Carl and Richard about the latest happenings in ASP.NET. They REALLY liked that we worked on the ConfigurationBuilders for INI files on the stream.
Next, I showed the two-factor authentication capabilities that come with the ASP.NET Core 2.0 templates that have “Individual Accounts” configured. I created a simple website using this template by executing the following at the command-line:
dotnet new mvc -au Individual -o MyProjectFolder
The “-au individual” bit of that command is the parameter passed into the “mvc” template to activate the Individual Account authentication capabilities.
I then tried to show a Windows project in a docker container, and had a problem with my Windows docker configuration. Quickly, I exited that failed demo and moved back to working on the Fritz.StreamTools project. We learned that when you open a project in Visual Studio that is using a different docker container operating system than what your docker tools are configured to use, Visual Studio will change that setting in your docker tools for you. Neat!
I fixed the presentation of the goal bar so that the bar would fill properly when updated from JavaScript. To make validating this fix easier, I added a test method to allow me to HTTP Post a new follower value and observe the bar growing. I used PostMan to execute and test this new API.
I then started adding SignalR to the project, and together we learned how to set up the Alpha version of SignalR that’s currently available.
SignalR is the ASP.NET and now ASP.NET Core framework for abstractly working with a web-server and getting “live” interaction with “push” capabilities to attached clients. Typically with HTML 5, you would do this with WebSockets. SignalR wraps the communication channel and abstractly allows any client to connect to the server using a SignalR client library.
This was as easy as adding the SignalR package reference to my csproj file:
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-alpha2-final" />
I then copied in the client-libraries from the npm package called @aspnet/signalr-client. I copied the signalr-client.min.js to the wwwroot/js folder so that I could reference it easily from the pages I wanted to “signalR-enable”
I add SignalR to my project, I added the following lines to my Startup/ConfigureServices method:
services.AddSignalR(); services.AddSingleton<FollowerHub>();
In my Configure method I mapped the Hub that I wanted to expose. A SignalR Hub is our live interaction point with the service, and my method to configure the Hub looks like this:
app.UseSignalR(configure => { configure.MapHub<FollowerHub>("followerstream"); });
I then wrote my simple FollowerHub.cs in a new Hubs folder with this content:
public class FollowerHub : Hub { public TwitchService Twitch { get; } public MixerService Mixer { get; } public FollowerHub( TwitchService twitch, MixerService mixer ) { this.Twitch = twitch; this.Mixer = mixer; Mixer.Updated += StreamService_Updated; Twitch.Updated += StreamService_Updated; } private void StreamService_Updated(object sender, ServiceUpdatedEventArgs e) { if (!e.NewFollowers.HasValue) { return; } Clients.All.InvokeAsync("OnFollowersCountUpdated", this.Mixer.CurrentFollowerCount + this.Twitch.CurrentFollowerCount); } }
Pretty easy to understand, as the Mixer and Twitch services are listened to for their Updated event to trigger. When either of them triggers the event, the “OnFollowersCountUpdated” method in my web page IN THE BROWSER of all connected clients is executed and passed the total number of followers. Easy to understand, and very cool to use. The configuration and definition of this method in the JavaScript hosted in the Goal HTML looks like this:
hubConnection.on('OnFollowersCountUpdated', data => { document.getElementsByClassName("current")[0].textContent = data; document.getElementsByClassName("current")[1].textContent = data; document.getElementById("progress").style.width = ((fullBarWidth * parseInt(data, 10) / goalValue) + 16) + "px"; });
On Thursday’s stream, we started by talking about events that I would be speaking at.. and you can find the complete list on my GitHub LiveStream Wiki. I also shared the good news about my book being published. You can find “Learn ASP.NET in 24 Hours” at Pearson and other places dead trees are sold.
We started by doing some simple refactoring on the StreamTools project, but found and merged a great pull-request from Bruno that finished integrating SignalR with the Followers count and goal views. We reviewed that pull-request and talked about how it works.
I refactored the notification of new followers and viewers into a standard Updated event with an accompanying event argument class called ServiceUpdatedEventArgs. This allows the code to listen for a specific argument that carries the values of the new viewers and followers on the various streaming services. Our presentation logic then does not need any specific knowledge of the services in order to repaint the viewer and follower counts.
In Saturday’s stream, we finally fixed the goal bar that was bleeding over on the top of the screen. I was happy to see the 500 number now properly fitting on the screen and not disappearing.
I spoke briefly about how to configure routes in ASP.NET Core, and we discussed the pros and cons of attribute-based routing compared to a defined routing table in the Startup class. In my opinion, this is a “what makes me a happy coder” decision. In smaller projects, it is easy to override with attributes on each method. When projects grow, it is nicer to have all of the route definitions in one place. There was a suggestion from the chat room that it would be cool to be able to refactor attribute routes into a common location, and I started a page on the Stream Wiki with project ideas for future streams.
I added some route constraints to the Follower Goals MVC action, which now enforces requirements in order to show the Follower Goals bar. This allowed me to add a secondary instance of the Goal action to my FollowerController that takes no arguments and instead delivers some documentation about the Follower Goal feature. … and I’ve been wanting to figure out where and how to self-document this application.
Next, I refactored the color configuration of the Follower Goal bar into a set of Configuration keys. This allowed me to easily change the color of the bar to red from blue by just changing a value in appsettings.json OR an environment variable.
Summary
This was a series of easy changes and enhancements to the StreamTools project this week. Next week, I plan to add new features like the ViewerCount and do some more refactoring to centralize the management of the streaming services. I hope you join me on Tuesday, Thursday, or Saturday morning at 10am ET (UTC-05:00)