The UWP WebView control has a Refresh() method that works fine for most pages, but calling the method directly after the WebView has been navigated somewhere by POST (e.g. a form submission inside the WebView itself) raises the NavigationStarted event, but never actually performs any refresh.
Here's some minimised XAML that demonstrates the issue:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Name="Refresh" Click="Refresh_Click" Content="Refresh" />
<WebView Grid.Row="1" Name="BrowserView" />
</Grid>
</Page>
Here's the relevant code-behind:
namespace App1
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
BrowserView.NavigationCompleted += BrowserView_NavigationCompleted;
BrowserView.NavigationStarting += BrowserView_NavigationStarting;
BrowserView.Navigate(new Uri("http://localhost/test.php"));
}
private void Refresh_Click(object sender, RoutedEventArgs e)
{
BrowserView.Refresh();
}
private void BrowserView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
// Always called on first load and when refreshed (even for POST results)
Debug.WriteLine($"Navigation starting for URI {args.Uri}");
}
private void BrowserView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
// Not called when a POST result is being refreshed
Debug.WriteLine($"Navigation completed");
}
}
}
As a test, I've created and hosted a very small PHP page with the following content and hosted it at http://localhost/test.php:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<form method="POST">
<p>Page loaded at <?php echo date('H:i:s') . (!empty($_POST['in']) ? ' with text "'.htmlspecialchars($_POST['in']).'"' : '') ?></p>
<input type="text" name="in" />
<input type="submit" />
</form>
</body>
</html>
Once I point my WebView at this page I can refresh the page on the initial load just fine, but after submitting the form, Refresh() raises the NavigationStarting event but does not navigate the page at all (as indicated by the timestamp on the test PHP result not changing) and never raises a corresponding NavigationCompleted event.
When the same page is visited in Edge, the user is shown this warning when attempting to refresh a POST result:
Choosing Retry resubmits the POST data to the server, and choosing Cancel behaves similarly to what I'm seeing (doing nothing at all). This dialog is obviously not emulated in any way by the UWP WebView control.
Since my actual application shows users a refresh button, I need the button to do something regardless of whether or not they've recently submitted a form, or alternatively I need to disable the refresh button so it's not confusing to users when the button does nothing.
Right now the only solution I have (which astonishingly seems to work, but is really nasty) is to call GoBack(), then in the NavigationCompleted event handler immediately call GoForward().
I could settle for an option that allows me to detect this condition (something like WebView.CanRefresh so that I could disable my Refresh button), or worst case scenario some kind of result/exception that allows me to communicate to the user what has (not) happened and why.
