I have a code like below,
public partial class LawView : UserControl
{
public LawView()
{
InitializeComponent();
InitializeAsync();
}
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
webView.Source = new System.Uri("https://blahblah.com.pl/");
webView.Focus();
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementById('user').value = 'blahblahusername'; document.getElementById('password').value = 'blahpassword'; })()");
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementsByName('wp-submit')[0].click(); })()");
}
}
in the console, the scripts run without any problems, but when I run them in the application, the fields in the open page do not fill me up. What am I doing wrong? Is there something missing?
I've already searched stackoverflow and other sites. I found nothing to lead me to a solution. I will be grateful for any help.
After setting the Source
property you need to wait for the page to actually load. You can use the NavigationCompleted event or the DOMContentLoaded for this. Note that NavigationCompleted
is called for successful and unsuccessful navigations.
extension
method to wrap the NavigationCompleted
event. The method uses the Navigate
method instead of setting the Source
property.// Create a static class and add the following extension method
// Add using System.Threading.Tasks;
public static Task NavigateToAsync(this CoreWebView2 coreWebView2, string url)
{
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
EventHandler<CoreWebView2NavigationCompletedEventArgs> evt = null;
evt = async (s, args) =>
{
coreWebView2.NavigationCompleted -= evt;
if (args.IsSuccess)
{
tcs.TrySetResult(true);
}
else
{
tcs.TrySetException(new Exception("Nav Failed With Error:" + args.WebErrorStatus.ToString()));
}
};
coreWebView2.NavigationCompleted += evt;
coreWebView2.Navigate(url);
return tcs.Task;
}
// Use extension method in your code.
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
try
{
await webView.CoreWebView2.NavigateToAsync("https://klimedsoft.pl/strefa-klienta/");
webView.Focus();
// now execute your javascript
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementById('user').value = 'blahblahusername'; document.getElementById('password').value = 'blahpassword'; })()");
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementsByName('wp-submit')[0].click(); })()");
}
catch (Exception ex)
{
//TODO: Handle error
}
}
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
webView.CoreWebView2.DOMContentLoaded += OnWebViewDOMContentLoaded;
webView.Source = new System.Uri("https://klimedsoft.pl/strefa-klienta/");
}
private async void OnWebViewDOMContentLoaded(object sender, CoreWebView2DOMContentLoadedEventArgs arg)
{
webView.CoreWebView2.DOMContentLoaded -= OnWebViewDOMContentLoaded;
webView.Focus();
// now execute your javascript
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementById('user').value = 'blahblahusername'; document.getElementById('password').value = 'blahpassword'; })()");
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementsByName('wp-submit')[0].click(); })()");
}
You didn't indicate if the web view navigated to the page at all.
Try using the Navigate(string url)
on the Core viewer.
The main issue is generally that we need to wait for the page load to complete before it will be ready to execute scripts. When you run this in the web console, you are doing so only after the page has loaded.
This response from @amaitland is generally the accepted solution for converting an event based API (EAP) to a Task based API (TAP). This pattern is generally referred to as a TAP Wrapper or TAP Extension. Find more information on that here:
My previous solution (which I will leave below) was a quick and dirty wait loop, we should however use SemiphoreSlim
instead of thread blocking logic to achieve the same thing. You can find out more information here:
This is a solution using SemaphoreSlim
:
private SemaphoreSlim _waitForWebViewToLoad;
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
_waitForWebViewToLoad = new SemaphoreSlim(0,1);
webView.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;
webView.CoreWebView2.Navigate("https://klimedsoft.pl/strefa-klienta/");
webView.Focus();
await _waitForWebViewToLoad.WaitAsync();
// now execute your javascripts
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementById('user').value = 'blahblahusername'; document.getElementById('password').value = 'blahpassword'; })()");
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementsByName('wp-submit')[0].click(); })()");
}
private void CoreWebView2_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)
{
webView.CoreWebView2.NavigationCompleted -= CoreWebView2_NavigationCompleted;
_waitForWebViewToLoad.Release();
}
The following is a similar approach that uses a simple boolean flag to indicate when the event has fired, the difference here it uses an infinite loop that blocks and then waits for 100 milliseconds. If you find yourself using this style of code, then SemaphoreSlim
was designed specifically to solve this problem without blocking the current thread:
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
webView.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;
navComplete = false;
webView.CoreWebView2.Navigate("https://klimedsoft.pl/strefa-klienta/");
webView.Focus();
while(!navComplete)
{
await Task.Delay(100);
}
// now execute your javascripts
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementById('user').value = 'blahblahusername'; document.getElementById('password').value = 'blahpassword'; })()");
await webView.CoreWebView2.ExecuteScriptAsync("(function() { document.getElementsByName('wp-submit')[0].click(); })()");
}
bool navComplete = false;
private void CoreWebView2_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)
{
webView.CoreWebView2.NavigationCompleted -= CoreWebView2_NavigationCompleted;
navComplete = true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With