.NET MAUI webview view actual HTML - c#

Is it possible to retrieve the HTML a .NET MAUI WebView is currently displaying?
If so, how?
Unfortunately, I can't find anything on it inside the official documentation.
.NET MAUI WebView documentation
I am trying to retrieve the currently displayed HTML as a string, after a JavaScript event changed the HTML body content, to read out some meta-data.

I don't think you can access it directly (like with WebView2). However you can call Javascript, which have access to the HTML :
string result = await webView.EvaluateJavaScriptAsync($"document.documentElement.innerHTML");

You may use Navigated event to detect if page changes:
In .xaml,
<WebView x:Name="webview" ... Navigated="webview_Navigated" />
In .cs, implement Event Handler
async void webview_Navigated(System.Object sender, Xamarin.Forms.WebNavigatedEventArgs e)
{
var webView = sender as WebView;
HttpClient client = new HttpClient();
// Get the html
var html = await client.GetStringAsync((webView.Source as UrlWebViewSource).Url);
}
Furthermore, you may want JS/C# interaction on MAUI WebView. You could refer to this SO issue: JS/.NET interact on MAUI WebView.
Hope it works for you.

Related

Disable runtime cache in Microsoft.Web.WebView2.Wpf

I am creating a webview2 wpf application, everything works well till now, but when I tried to load HTML file which is having youtube link, It's worked well along with autoplay .
But when I change the HTML file to some another site , the audio of youtube video still playing in background and webview2 load the new content.
I want something to disable the cache to be stored will runtime instead of clearing the cache.
If someone is having any idea related to above issue please help
This is the common issue faced by the webview2 when external site media player is played.
To overcome this issue you have to create a new instance of webview2 before you load second content to webView, this will create new Webview Page but still the UI will not stop the audio, so use Webview.dispose() as well.
WebView.Dispose()
Note : this will give you issue related to Null object reference for the 1st time .
So you have the check the the object before doing dispose.
Code should be like this :
MainPage :
WebViewPage webpage;
private void updateNewContent ()
{
...
WebView2 webView2 = Mywebvew2; // MYwebview2 is UI object from webviewPage,
//you have to pass this object from webview Page
if (webView2 != null)
{
webView2.Dispose();
}
webpage = null;
webpage = new WebViewPage();
GridPrincipal.Children.Add(webpage);
...
}

How to properly display the current and real url loaded in a WebBrowser control?

In my Form, I added a WebBrowser and a TextBox on which I would like to display the current loaded Url.
Note what the Microsoft Docs says:
WebBrowser.Navigating event:
Occurs before the WebBrowser control navigates to a new document
WebBrowser.Navigated event:
Occurs when the WebBrowser control has navigated to a new document and has begun loading it.
...
Handle the DocumentCompleted event to receive notification when the WebBrowser control finishes loading the new document.
WebBrowser.DocumentCompleted event:
Occurs when the WebBrowser control finishes loading a document
...
Handle the DocumentCompleted event to receive notification when the new document finishes loading. When the DocumentCompleted event occurs, the new document is fully loaded
The order at which the events are fired is: Navigating, Navigated and DocumentCompleted, so I'm handling those events to try properly update the current url:
private void WebBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
this.TextBox1.Text = e.Url.ToString();
}
private void WebBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
this.TextBox1.Text = e.Url.ToString();
}
private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
this.TextBox1.Text = e.Url.ToString();
}
The problem is that for some reason the url does not seem to properly update for some websites...
For example when navigating through Google's search engine, if I do click on the Google Images button, the url updates to "http://www.google.com/blank.html". Also, the urls that I get to display in my TextBox are not the same exact urls as I can see in Firefox or Chrome's address bar; for some reason my obtained urls have additional parameters in the query.
See it by yourself:
https://i.imgur.com/PQlSu47.gif
Is there any workaround to improve this annoying behavior so I can display the current url with efficiency as Firefox or Chrome does?. I mean, for example Firefox and Chrome will not show "http://www.google.com/blank.html" in the addres bar, neither will not show the url queries with additional parameters as I got to display (which you can see in the GIF image above).
Please note that the problem with Google website is just as an example. I'm asking for a universal solution due this issue occurs with many more websites.
Also note that if instead the WebBrowser component I use CefSharp's chromium based web browser, adapting my code to reproduce the same as I was doing to display/update the current url, then the problem is partially gone...
Using CefSharp does not shows "http://www.google.com/blank.html" when navigating through Google Images, however the query of the urls still contain additional parameters / many differences in comparison from the urls displayed in Firefox or Chrome browsers.
And apart from that, I would like to avoid using CefSharp just for solving this kind of issue...
TL;DR
Instead of URL in the event args, use URL from the web browser control:
string url = webBrowser1.Url.ToString();
The long answer
What you are missing here is that the HTML page can contain iframe elements. An iframe encapsulates HTML Window and the contained HTML Document, and it performs its own navigation. The navigation events of the WebBrowser control fire for both the top window (for which you want to display the URL) and for the iframe's. You will have to distinguish between the two.
Specifically, in your case http://www.google.com/blank.html comes from an iframe:
<html> <!-- top window -->
<body> <!-- top window's document -->
<iframe src="http://www.google.com/blank.html">
<!--
here the browser will load and "insert" HTML of blank.html
lines below don't exist in the original HTML
they are loaded and "inserted" here by the browser
-->
<html> <!-- iframe's window -->
<body> <!-- iframe's window's document -->
<!-- the body can contain additional iframes... -->
</body>
</html>
</iframe>
</body>
</html>
In general, the DOM of an HTML page is a tree of HTML Window objects, with the root window returned by the window.top property. Depending on how the page is designed, iframe's can be visible or hidden; they can be rendered in HTML by server, and also be manipulated, created, or deleted dynamically in the browser through JavaScript:
when a new iframe is created, it performs navigation to URL specified in its src attribute. If neither src nor embedded contents are specified, the navigation URL will be about:blank.
when src attribute of an existing iframe is modified, the iframe will perform navigation to the new src.
when window.location is modified of either top or iframe HTML Window, it will perform navigation to the new location.
However, determining which HTML Window (top or iframe) performs the navigation doesn't seem to be a trivial task, so a simpler approach would be just getting URL of the top window:
string url = webBrowser1.Url.ToString();
or after the DocumentCompleted event:
HtmlWindow topWindow = webBrowser1.Document.Window;
string url = topWindow.Url.ToString();
The DocumentCompleted can be fired multiple times for a given URL, because a page can contain iframes that also trigger the event. So I suggest that you update the textbox at Navigating and Navigated events only.

C# Webbrowser control, mismatch between displayed content and Document.innerHtml

So I have a website which I load into my form's webbrowser control. After loading the document, I retrive the webbrowser.documenttext . I am looking here to parse specific table. But I am not finding the table in here but I see that it is being dispayed in the form browser.
I tell you that this specific table is being loaded/appended to doc by already loaded javascript code.
When I right click and select the "View Source" , it pops the document with correct html.
My question is how can I get the same document referenced by ViewSource or is there any way to get the document what is being rendered on form?
Instead of using Webbrowser Control use HtmlAgilityPackage to parse data based on your need.
var html = new HtmlDocument();
html.LoadHtml(new WebClient().DownloadString("http://www.asp.net"));
var root = html.DocumentNode;
var commonPosts = root.Descendants().Where(n => n.GetAttributeValue("class",
"").Equals("common-post"));
Similar Existing Question
The above issue was very similar to my issue and after going thorough the answer I learnt that I somehow need to wait and poll the webbrowser to get the dynamic content.
I did not really implement the code provided in the answer but I changed my documentCompleted event as async and provided a await task delay of 5s
private async void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
await Task.Delay(5000);
var html= wb.Document.GetElementsByTagName("HTML")[0].OuterHtml;
}
Now I get the dynamic result. Thanks, I am feeling now.

Script is not working in WebView in UWP

I am using following web view in xaml.
<WebView x:Name="FBCommentsTest"></WebView>
And i am trying to embed HTML data to that web view in the following way in the c# end.
FBCommentsTest.NavigateToString("<html><head></head><body><div id=\"fb-root\"></div><div id=\"fb-root\"></div><script>(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = \"http://connect.facebook.net/en_US/all.js#xfbml=1&appId=" + APP_KEY + "\";fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));</script><div class=\"fb-comments\" data-href=\""
+ mExternalUrl + "\" data-width=\"500\"></div> </body></html>");
But, in the web view i am getting an empty screen not able to get the facebook comments view.
How to enable the script in web view in uwp.
Please help me.
Thanks.
But, in the web view i am getting an empty screen not able to get the facebook comments view. How to enable the script in web view in uwp.
The NavigateToStringmethod does not provide a way to generate or provide css, scripts, images, and fonts resources programmatically. You can refer to WebView.NavigateToString method.
You can transfer your string into HTML file, and use Navigate method to navigate to the HTML page. Just for example, create a HTMLPage file in the project and code for it, then in the c# code behind:
Uri uri = new Uri("ms-appx-web:///HTMLPage1.html");
FBCommentsTest.Navigate(uri);

WebBrowser control must reload content every time app page is revisited (Windows Phone 7, Silverlight)

I'm writing an app for Windows Phone 7/Silverlight. When the app is either tombstoned and reactivated while on the app page containing the WebBrowser control (I've saved the Uri in app state) or that same app page is navigated to by NavigationService.GoBack() or the phone back button, it seems that as long as the control still has the webbrowser.source value, it should then render just fine, but this is not the case. Unless I use the Navigate() method, it shows a white/blank screen, no matter what I try. Unfortunately, using the Navigate() method causes the web content to download again, unnecessarily. It's especially frustrating when only a GoBack() is used to get back to the application page with the WebBrowser control, which is quite frequent in my app.
private void OnWebBrowserLoaded(object sender, RoutedEventArgs e)
{
//webBrowser1.Source = CurrentUri; //does not work, results in white/blank browser page
webBrowser1.Navigate(CurrentUri); //works, but page has to reload from web, bad UX
}
Any suggestions on a way around this problem? I've also tried putting this same code in the page loaded handler. It behaves in the same poor manner.
I've also tried saving off the HTML (SaveToString) and reloading it from app state (NavigateToString), but the web page does not render completely for some reason, even though the HTML appears fine. Also, I'd like to have access to the Host and Uri properties. I could probably work around that, if I could get the HTML to render OK from NavigateToString.
Thanks,
Jay
You should use browsertask:
using Microsoft.Phone.Tasks;
WebBrowserTask browse = new WebBrowserTask();
browse.Uri = new Uri(URL, UriKind.RelativeOrAbsolute);
//new Uri(URL,UriKind.RelativeOrAbsolute);
browse.Show();
This should solve your issue.
URL will be the URL of the page you want to visit.

Categories