I have a WPF desktop app that I use to navigate games and streams on Twitch using their API. Roughly 2 weeks ago (mid/late Feb 2018) I started noticing that stream preview images were no longer loading (the <Image />
tag took up no space in the layout).
The images were loaded very simply. For the sake of demonstration I've chosen a 24/7 stream.
<Image Source="https://static-cdn.jtvnw.net/previews-ttv/live_user_esl_sc2-640x360.jpg" />
This URL comes from the API and works fine in a browser. In the process of testing this I created a basic WPF app.
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Source="https://static-cdn.jtvnw.net/previews-ttv/live_user_esl_sc2-640x360.jpg" />
</Grid>
</Window>
This ended up working, which I eventually realized was because the new project had a target framework of .NET 4.6.1. Switching it to 4.5.X caused it to yield the same result as the other app. Switching the first app to 4.6.X caused it to work again. .NET 4.0 also fails. Other websites (e.g. Imgur) work without incident. Maybe also worth noting that there's no preview image in the designer window when using the Twitch url on any .NET framework, but there is one for Imgur.
The issue occurs on two Windows 10 devices and a Windows 7 device. I believe one of the Windows 10 devices has regular windows updates (might be disabled, not sure), while the other two have updates set to manual-only.
What is causing this behavior?
It appears that Twitch is now serving the images via HTTP/2. I believe that HTTP requests under the older .NET are being defaulted to using SSL3 and that's being rejected by Twitch.
Aside from upgrading the version of .NET to 4.6.x or greater, setting the security protocol also fixes the problem:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;