Tuesday, July 29, 2025

Wierd issues in the WinUI3 / WebView2: Solving the User-Agent problem

 TL/DR: To verify that you are setting the right user-agent, you have to check the "web resource requested" event's copy of the request headers, not the "navigation starting" event's copy. And you need to call AddWebResourceRequestedFilter.


Background: why am I setting the user-agent, and why do I need to check it?

I'm writing a simple app to parse NMEA data from a small GPS tracker (because that's what I do for fun, that's why). I'm at the part of the project where I want to make a GPS trace, and the technology I've picked is the Open Street Maps project using the leaflet JavaScript library. It's actually really nice: it works smoothly, and the integration was mostly simple.

But ... one of the requirements Open Street Maps has is that if you make an app that works against their servers, you have to use a custom User-Agent header in the HTTP requests. This makes sense: they can filter requests based off of the user-agent if needed.

After a bit of work, it's not hard to set the user-agent. But how to verify that it's correct? The easiest way was to set an event handler on the WebView2 NavigationStarted event. That event provides a CoreWebView2NavigationStartingEventArgs object that includes the request headers. I just have to iterate through them (easy-peasy) and they check the User-Agent value.

And it's not set!

Side quest #1: timing

Web searches show that people do have trouble setting the User-Agent. In particular, it must be set before you get a navigation started event. But in my app, that's not a problem.

Side quest #2: threads and services

The documentation also helpfully points out that the user-agent is thoroughly screwed up if you have multiple WebView2 objects. Each object might well share some of the underlying bits, and so when you have two WebView2 objects, and the user-agent is set differently on them, you might well have the the wrong user-agent sent. This is just dumb, but I remember from previous work with Edge that it's a pretty complex beast.

Solution: check based on the WebResourceRequested event. This requires setting the event in a different place than normal (it must be set after calling the EnsureCoreWebView2Async method). It also requires setting a WebResourceRequestFilter, which hopefully won't cause a slowdown in my app. That callback also includes all of the request headers, and those headers show the correct User-Agent. 

Links: see my question at Setting a WebView2 UserAgent isn't updated in the NavigationStarting event - Microsoft Q&A

 


No comments: