ElektroStudios
ElektroStudios

Reputation: 20494

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:

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.sstatic.net/0PX5A.gif

enter image description here

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...

Upvotes: 2

Views: 1594

Answers (2)

felix-b
felix-b

Reputation: 8498

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();

Upvotes: 2

Theodor Zoulias
Theodor Zoulias

Reputation: 43941

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.

Upvotes: 2

Related Questions