Stream Wrap Up – SignalR and Refactoring for Unit Testing Madness

The weekly scramble is over, and I think we accomplished a lot in building overlays and answering questions this week.  Let’s review the progress from this week’s streams:

We started with a question from djvortechs about referencing packages from Visual Studio extension projects, or VSIX’s.  After a little exploration, I couldn’t come up with the immediate answer.  In a follow-up discussion with Mads Kristensen on Twitter, he indicated that the package we were trying to reference, Newtonsoft.Json is distributed with Visual Studio and was not needed to be included in the redistributable VSIX package.

I started work on the Fritz.StreamTools project with a simple refactoring to centralize all references to sending a command to all attached SignalR clients.  This new FollowerClient class allowed me to write the “magic string” containing the SignalR client-side function name.

public class FollowerClient

  public FollowerClient(IHubContext<FollowerHub> followerContext)

    this.FollowerContext = followerContext;


  private IHubContext<FollowerHub> FollowerContext { get; }

  public void UpdateFollowers (int newFollowers) {

      .InvokeAsync("OnFollowersCountUpdated", newFollowers);



The FollowerContext is a reference to the server-side Hub that our clients are listening on.  Whenever we need to update the follower count on attached clients, the UpdateFollowers method can send that new follower count to all clients that have a “OnFollowersCountUpdated” client-side method.

I then started writing a simple RazorPage to present the current viewers from both Twitch and Mixer services, with a goal to emulate the widget that currently resides in the top-right corner of the video.  This new page, CurrentViewers.cshtml, contains very similar markup to the Followers goal widget that I constructed previously.  I copied and pasted some of the Followers code to drive updating this new Current Viewers widget.

On Thursday’s stream, I ran into a brief GitHub outage… and that lead to some fun with chromakey and the GitHub pink unicorn error message.

Jeff is angry at the GitHub Unicorn

I now have a new error page template

Big thanks to Carey Payette for capturing that second pic of me during the stream as I was playing with the GitHub error page.

I started by adding a .EditorConfig file to the Fritz.StreamTools project to help enforce some standards in code formatting and syntax.  Additionally, I set the TreatWarningsAsErrors property in the project’s csproj file to true.  When the EditorConfig extension is in place in Visual Studio, it will throw errors during the build process if my rules are violated.  This should also help with ensuring that my files are formatted with my preferences, like preferring tabs over spaces.

Next, we looked at how I added a logger to the interactions with the Twitch and Mixer services.  This allows those services to report to the container’s logs when changes in the service state occur.

Next, I started using PowerShell to maintain the files committed to Git source control.  The module that I prefer to use with PowerShell for Git highlighting, tab-completion, and prompt enhancements is called posh-git.  It was really easy to install from the PowerShell command-line in Windows 10:

  1. PowerShellGet\Install-Module posh-git -Scope CurrentUser
  2. Import-Module posh-git
  3. Add-PoshGitToProfile

More details including permission configuration is available on the posh-git project page.

Next, I performed a refactoring where I moved the contents of the Startup.ConfigureServices method to another class in order to simplify the contents of the Startup class.  This is a very important class, and with the volume of content in it, the chances of inadvertently breaking something was starting to grow.  I simplified by creating a class in a folder called “StartupServices” called “ConfigureServices” that has a single method, Execute and would do the same things as the former Startup.ConfigureServices method.

I re-arranged the code in that Execute method, and even added some groupings by moving some of the similar configuration into private methods.  I think this now makes the configuration of services for this project a bit easier to manage, and defends the Startup class against invalid updates.  In the future, we can write some unit-tests against the ConfigureServices class to ensure that our configuration is being applied properly.

Then, we merged a pull-request from Bruno that rolled up the various streaming services into an aggregate StreamService object.  This was really great because all of the user-interface work in the project could be refactored to remove their direct references to Twitch or Mixer.  Really great stuff, and a good step towards making our code more testable.

I made my application a little bit easier to tweak and re-run by using the dotnet watch feature.  This was added to my project by adding the Microsoft.DotNet.Watcher.Tools reference to my project file and then executing on the command line “dotnet watch run”.  This would re-start the application whenever a server-side file changed on disk.

We updated the CurrentViewers razor page to take advantage of this new aggregate StreamService, and output the collection of services and viewer counts by using a simple Linq query.  Then, I received a comment in the chat room that suggested I use the JavaScript array reduce feature to update the total viewer count, instead of using a for..loop to sum the values.  This JavaScript code to sum the values for the Total Viewers element looks like:

const reducer = (accumulator, currentValue) => 
   accumulator + parseInt(currentValue.textContent, 10);
var currentCounts = document.getElementsByClassName("serviceCount");
var elArray = Array.from(currentCounts);
document.getElementById("totalCount").textContent = elArray.reduce(reducer, 0);

The reducer function receives an accumulator value and the currentValue that it should be operating on.  The currentCounts object is a collection of HTML elements with the CSS class “serviceCount”, and is converted to an array using the Array.from statement.  Finally, the totalCount textContent is set to the result value of the reducer function operating on each element of the elArray, with an initial accumulator value of 0.

Finally, I added a check to only add the Twitch and Mixer services when a ClientID is configured for those services.  With this indirect reference to these services in use now, we should be able to conditionally add services as they are configured.

On Saturday’s stream, we started by answering some questions about the new Span feature and also a question about how and where to get a comprehensive teaching experience online for .NET Core development. Of course, you can check out Microsoft Virtual Academy and the .NET Core courses that I have written as well as my book about Learning ASP.NET in 24 hours.

In this stream, I focused on adding unit tests to the solution.  My primary way of executing unit tests is in Visual Studio 2017, and I showed how to run tests manually and also the Live Unit Testing feature of the Enterprise edition of Visual Studio.  Also, I showed that the dotnet watch tool could be used for testing as well just by running “dotnet watch test” against my test project.

I started with some simple tests to verify that the count of followers and viewers was summed properly, and then moved on to testing the more complex interaction of verifying that the output from Twitch was handled properly by the application.

There were some questions about PHP and unit testing during the stream.  I suggested folks check out the Peachpie project, which enables PHP applications to be compiled with the .NET roslyn compiler.  Jakub Misek from the Peachpie project spoke about the features during dotNetConf 2017, and that video is below:

We then wrote some more complex tests to inspect the events raised when the Twitch service raises the Updated event. To do this, we used the xUnit event testing feature that looks like this:

var evt = Assert.Raises<ServiceUpdatedEventArgs>(
  h => sut.Updated += h,
  h => sut.Updated -= h,
  () => sut.Service_OnNewFollowersDetected(null, myArgs)

Assert.Equal(initialFollowers + newFollowerCount, evt.Arguments.NewFollowers);

The Raises method takes a type parameter that matches the arguments type of the Event we are looking for, attaches and detaches from the Updated event in the first two arguments, and the third parameter is the method call that should trigger the Updated event.  The return value from the Raises method is a wrapper around this Updated event that we can inspect on the last two lines of the sample.

Overall some good progress this week.  Next week, we’re going to start the week with completing the YamlConfigurationBuilder from the ConfigurationBuilders project.  Later, we should have a guest on Thursday or Saturday morning.  Keep an eye on the stream and my Twitter account for updates about the content planned this week.  I hope to see you then!

Live Stream Wrapup – Security, ASP.NET Core and SignalR

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.

Continue reading

My Amazon Account was Hacked and How I Made it More Secure

My Amazon account was recently hacked, and I was NOT thrilled when I discovered this unfortunate problem.  I’m going to share how I discovered my account was hacked, what I did about it, how it was resolved, and what you can do to secure your personal accounts.  I will write another article about making our systems more secure for our customers.

Continue reading

Stream Wrap-up: Personal Security and Renaming a Project

Today’s stream didn’t deliver much in terms of new code, but I think it had a bit of value.  Over the last 24 hours, my Amazon account was hijacked.  I started the stream discussing what happened as well as the steps I am taking to remedy it. Then, I fixed an issue with Epic Build Music, and then did the tedious renaming of the Rundown project.

Continue reading