导航

本指南描述了导航事件并展示了如何加载 URL 和文件、过滤导航请求、处理导航历史等。

加载 URL

要导航到由 URL 标识的资源,请使用以下方法之一:

  • INavigation.LoadUrl(string url)
  • INavigation.LoadUrl(LoadUrlParameters parameters)

下面的示例展示了如何使用 INavigation.LoadUrl(string) 方法导航到 https://www.google.com

INavigation navigation = browser.Navigation;
navigation.LoadUrl("https://www.google.com");
Dim navigation As INavigation = browser.Navigation
navigation.LoadUrl("https://www.google.com")

同步加载 URL

LoadUrl 方法向给定资源发送一个导航请求并返回一个Task<NavigationResult> ,该任务可用于等待资源完全加载完成。

如果您需要阻塞当前线程执行直到资源完全加载,请使用 Task.Wait() 方法:

navigation.LoadUrl("https://www.google.com").Wait();
navigation.LoadUrl("https://www.google.com").Wait()

该方法会阻塞当前线程执行,直到资源的主框架被完全加载或直到达到默认的 100 秒超时时间为止。

如果导航失败,返回的 Task<NavigationResult> 将完成,其Task.Result 属性将返回有关可能的导航失败的详细信息。

如果资源在给定的时间内未加载,则会抛出 TimeoutException 异常。

当主框架至少发生以下事件之一,即 FrameLoadFinished, NavigationFinished, 或 FrameLoadFailed 时,网页被视为已完全加载。

使用 POST 加载 URL

要通过 URL 加载网页并发送 POST 数据,请使用 INavigation.LoadUrl(LoadUrlParameters) 方法。 下面的代码演示了如何使用额外的标头加载 URL 和发送不同格式的 POST 数据。

你可以以 key=value 的格式向网络服务器发送网路表单数据:

navigation.LoadUrl(new LoadUrlParameters("https://postman-echo.com/post")
{
    UploadData = new FormData(new Dictionary<string, string>()
    {
        {"key", "value"}
    })
});
navigation.LoadUrl(New LoadUrlParameters("https://postman-echo.com/post") With {
    .UploadData = New FormData(New Dictionary(Of String, String)() From {
        {"key", "value"}
    })
})

您需要为每种请求类型明确指定 “Content-Type” 标头。

如果您想发送一些纯文本,请添加额外的标头来指示网络服务器它是纯文本:

navigation.LoadUrl(new LoadUrlParameters("https://postman-echo.com/post")
{
    UploadData = new TextData("Some text..."),
    HttpHeaders = new[]
    {
        new HttpHeader("Content-Type", "text/plain")
    }
});
navigation.LoadUrl(New LoadUrlParameters("https://postman-echo.com/post") With {
    .UploadData = New TextData("Some text..."),
    .HttpHeaders = 
    { 
        New HttpHeader("Content-Type", "text/plain") 
    }
})

您可以发送任何类型的数据。 为此,请指定其 Content-Type。 请参阅下面发送 JSON 数据的代码示例:

navigation.LoadUrl(new LoadUrlParameters("https://postman-echo.com/post")
{
    PostData = "{\"title\":\"Hello\"}",
    HttpHeaders = new[]
    {
        new HttpHeader("Content-Type", "application/json")
    }
});
navigation.LoadUrl(New LoadUrlParameters("https://postman-echo.com/post") With {
    .PostData = "{""title"":""Hello""}",
    .HttpHeaders = 
    { 
        New HttpHeader("Content-Type", "application/json") 
    }
})

加载文件

您可以使用相同的方法从本地文件系统加载 HTML 文件,方法是提供 HTML 文件的绝对路径而非 URL。 请参阅以下代码示例:

navigation.LoadUrl(Path.GetFullPath("index.html"));
navigation.LoadUrl(Path.GetFullPath("index.html"))

加载 HTML

要将 HTML 加载到浏览器中,您可以创建一个 data: 编码的 URI,然后使用常规的 LoadUrl 调用加载它。 下面是一个例子:

var html = "<html><head></head><body><h1>Html Encoded in URL!</h1></body></html>";
var base64EncodedHtml = Convert.ToBase64String(Encoding.UTF8.GetBytes(html));
browser.Navigation.LoadUrl("data:text/html;base64," + base64EncodedHtml).Wait();
Dim html = "<html><head></head><body><h1>Html Encoded in URL!</h1></body></html>"
Dim base64EncodedHtml = Convert.ToBase64String(Encoding.UTF8.GetBytes(html))
browser.Navigation.LoadUrl("data:text/html;base64," & base64EncodedHtml).Wait()

Chromium 将数据编码 URI 的最大长度限制为 2MB。

但是,使用此方法时无法设置基本 URL。

另一种可能的方法是使用处理程序注册一个 Scheme 并拦截相应的请求以提供 HTML。 请参阅相应的文章.

重载

有几种重新加载当前加载的网页的选项:

  • 使用 HTTP 缓存重新加载:
navigation.Reload();
navigation.Reload()
  • 忽略 HTTP 缓存重新加载:
navigation.ReloadIgnoringCache();
navigation.ReloadIgnoringCache()
  • 使用 HTTP 缓存重新加载并检查是否重新发布:
navigation.ReloadAndCheckForRepost();
navigation.ReloadAndCheckForRepost()
  • 忽略 HTTP 缓存重新加载并检查是否重新发布:
navigation.ReloadIgnoringCacheAndCheckForRepost();
navigation.ReloadIgnoringCacheAndCheckForRepost()

停止

使用 INavigation.Stop() 方法取消任何挂起的导航或下载操作,并停止任何动态页面元素,例如背景声音和动画。 请参阅以下代码示例:

navigation.Stop();
navigation.Stop()

后退 & 前进

DotNetBrowser 允许使用导航后退-前进历史列表。

当您创建一个 IBrowser 实例时,它默认导航到 about:blank 网页。 在导航后退-前进列表中始终有一个条目。

要加载后退-前进列表中的前一个位置,请使用以下方法:

if (navigation.CanGoBack()) {
    navigation.GoBack();
}
If navigation.CanGoBack() Then
    navigation.GoBack()
End If

要加载后退-前进列表中的下一个位置,请使用以下方法:

if (navigation.CanGoForward()) {
    navigation.GoForward();
}
If navigation.CanGoForward() Then
    navigation.GoForward()
End If

要导航到后退-前进列表中特定索引处的条目,请使用以下方法:

if (index >=0 && index < navigation.EntryCount) {
    navigation.GoTo(index);
}
If index >=0 AndAlso index < navigation.EntryCount Then
    navigation.GoTo(index)
End If

要翻阅后退-前进列表并获得每个导航条目的详细信息,请使用以下方法。

for (int index = 0; index < navigation.EntryCount; index++) {
    INavigationEntry navigationEntry = navigation.EntryAt(index);
    Console.WriteLine("URL: " + navigationEntry.Url);
    Console.WriteLine("Title: " + navigationEntry.Title);
}
For index As Integer = 0 To navigation.EntryCount - 1
    Dim navigationEntry As INavigationEntry = navigation.EntryAt(index)
    Console.WriteLine("URL: " & navigationEntry.Url)
    Console.WriteLine("Title: " & navigationEntry.Title)
Next

要通过删除条目来修改后退-前进列表,请使用以下方法。

// 返回后退/前进列表中的条目数。
int entryCount = navigation.EntryCount;
// 删除索引处的导航条目。
for (int i = entryCount - 2; i >= 0; i--) {
    bool success = navigation.RemoveEntryAt(i);
    Console.WriteLine("Navigation entry at index " + i +
            " has been removed successfully? " + success);
}
' 返回后退/前进列表中的条目数。
Dim entryCount As Integer = navigation.EntryCount
' 删除索引处的导航条目。
For i As Integer = entryCount - 2 To 0 Step -1
    Dim success As Boolean = navigation.RemoveEntryAt(i)
    Console.WriteLine("Navigation entry at index " & i & 
                      " has been removed successfully? " & success)
Next

过度滚动历史导航

在硬件加速渲染模式下,DotNetBrowser 允许通过在带有触摸屏的设备上向左/向右滑动来后退/前进导航。 默认情况下,过度滚动导航是禁用的。 要启用它,请使用 IBrowserSettings.OverscrollHistoryNavigationEnabled 属性:

browser.Settings.OverscrollHistoryNavigationEnabled = true;
browser.Settings.OverscrollHistoryNavigationEnabled = True

过滤 URL

您可以决定是否忽略特定 URL 的导航请求。

请参阅下面的代码示例,其中展示了如何忽略所有以 https://www.google 开头的 URL 的导航请求:

navigation.StartNavigationHandler = 
    new Handler<StartNavigationParameters, StartNavigationResponse>((p) =>
    {
        // 忽略以 "https://www.google" 开头的 URL 
        // 导航请求。
        if (p.Url.StartsWith("https://www.google"))
        {
            return StartNavigationResponse.Ignore();
        }
        return StartNavigationResponse.Start();
    });
navigation.StartNavigationHandler = 
    New Handler(Of StartNavigationParameters, StartNavigationResponse)(Function(p)
        ' 忽略以 "https://www.google" 开头的 URL 
        ' 导航请求。
        If p.Url.StartsWith("https://www.google") Then
            Return StartNavigationResponse.Ignore()
        End If
        Return StartNavigationResponse.Start()
    End Function)

过滤资源

SendUrlRequestHandler “处理程序可让您确定 HTML、图像、JavaScript 或 CSS 文件、favicon 等资源是否已加载。 默认情况下,加载所有资源。 要修改默认行为,请在您决定取消或加载哪些资源的地方注册您自己的处理程序实现。

请参阅下面的代码示例,了解如何抑制所有图像:

engine.Network.SendUrlRequestHandler =
    new Handler<SendUrlRequestParameters, SendUrlRequestResponse>(p =>
    {
        if (p.UrlRequest.ResourceType == ResourceType.Image)
        {
            return SendUrlRequestResponse.Cancel();
        }
        return SendUrlRequestResponse.Continue();
    });
engine.Network.SendUrlRequestHandler = 
    New Handler(Of SendUrlRequestParameters, SendUrlRequestResponse)(Function(p)
        If p.UrlRequest.ResourceType = ResourceType.Image Then
            Return SendUrlRequestResponse.Cancel()
        End If
        Return SendUrlRequestResponse.Continue()
    End Function)

导航事件

加载网页是一个复杂的过程,其中会触发导航事件。 下图展示了加载网页时可能触发的导航事件的顺序: Navigation Events Flow

加载开始

要在内容加载开始时获得通知,请使用 LoadStarted 事件。 请参阅以下代码示例:

navigation.LoadStarted += (s, e) => {};
AddHandler navigation.LoadStarted, Sub(s, e)
End Sub

该事件对应于标签页的加载指示器开始旋转的时刻。

加载完成

要在内容加载完成时获得通知,请使用 LoadFinished 事件。 例如:

navigation.LoadFinished += (s, e) => {};
AddHandler navigation.LoadFinished, Sub(s, e)
End Sub

该事件对应于标签页的加载指示器停止旋转的时刻。

加载进度

LoadProgressChanged 事件允许获取有关加载进度的通知:

navigation.LoadProgressChanged += (s, e) =>
{
    // 表示网页加载进度的值。
    double progress = e.Progress;
};
AddHandler navigation.LoadProgressChanged, Sub(s, e)
    ' 表示网页加载进度的值。
    Dim progress As Double = e.Progress
End Sub

导航开始

要在导航开始时获得通知,请使用 NavigationStarted 事件。 请参阅以下代码示例:

navigation.NavigationStarted += (s, e) => 
{
    string url = e.Url;
    // 指示导航是否
    // 将在同一文档范围内执行。
    bool isSameDocument = e.IsSameDocument;
};
AddHandler navigation.NavigationStarted, Sub(s, e)
    Dim url As String = e.Url
    ' 只是导航是否
    ' 将在同一文档范围内执行。
    Dim isSameDocument As Boolean = e.IsSameDocument
End Sub

导航停止

要在导航停止时获得通知,请使用 NavigationStopped 事件。 请参阅以下代码示例:

navigation.NavigationStopped += (s, e) => {};
AddHandler navigation.NavigationStopped, Sub(s, e)
End Sub

当使用 Navigation.stop() 方法停止导航时会触发此事件。

导航重定向

要在导航重定向到新 URL 时获得通知,请使用 NavigationRedirected 事件。 请参阅以下代码示例:

navigation.NavigationRedirected += (s, e) => {
    // 导航重定向 URL。
    string url = e.Url;
};
AddHandler navigation.NavigationRedirected, Sub(s, e)
    ' 导航重定向 URL。
    Dim url As String = e.Url
End Sub

导航完成

要在导航完成时获得通知,请使用 NavigationFinished 事件。 请参阅以下代码示例:

navigation.NavigationFinished += (s, e) => {
    string url = e.Url;
    IFrame frame = e.Frame;
    bool hasCommitted = e.HasCommitted;
    bool isSameDocument = e.IsSameDocument;
    bool isErrorPage = e.IsErrorPage;
    if (isErrorPage) {
        NetError error = e.ErrorCode;
    }
};
AddHandler navigation.NavigationFinished, Sub(s, e)
    Dim url As String = e.Url
    Dim frame As IFrame = e.Frame
    Dim hasCommitted As Boolean = e.HasCommitted
    Dim isSameDocument As Boolean = e.IsSameDocument
    Dim isErrorPage As Boolean = e.IsErrorPage
    If isErrorPage Then
        Dim [error] As NetError = e.ErrorCode
    End If
End Sub

当导航被提交、中止或被新导航替换时,将触发此事件。 要知道导航是否已提交,请使用 NavigationFinishedEventArgs.HasCommitted。 要了解导航是否导致错误页面,请使用 NavigationFinishedEventArgs.IsErrorPage

如果由于导航已提交而调用该事件,则文档加载仍将继续进行。

该事件由 same-document(在同一文档范围内)的导航触发,比如片段导航或 window.history.pushState()/window.history.replaceState(),这些导航不会导致文档的更改。 使用 NavigationFinishedEventArgs.IsSameDocument 属性来检查是否是同一文档导航。

框架加载完成

要在 IFrame 中的内容加载完成时获得通知,请使用 FrameLoadFinished 事件。 请参阅以下代码示例:

navigation.FrameLoadFinished += (s, e) =>
{
    string url = e.ValidatedUrl;
    IFrame frame = e.Frame;
};
AddHandler navigation.FrameLoadFinished, Sub(s, e)
    Dim url As String = e.ValidatedUrl
    Dim frame As IFrame = e.Frame
End Sub

此事件对应于 Frame 中的内容已完全加载的时刻。

框架加载失败

要在 Frame 中的内容加载因某种原因失败时获得通知,请使用 FrameLoadFailed 事件。 请参阅以下代码示例:

navigation.FrameLoadFailed += (s, e) =>
{
    string url = e.ValidatedUrl;
    NetError error = e.ErrorCode;
};
AddHandler navigation.FrameLoadFailed, Sub(s, e)
    Dim url As String = e.ValidatedUrl
    Dim [error] As NetError = e.ErrorCode
End Sub

框架文件加载完成

要在 Frame 中的文档加载完成时获得通知,请使用FrameDocumentLoadFinished 事件。 请参阅以下代码示例:

navigation.FrameDocumentLoadFinished += (s, e) => 
{
    IFrame frame = e.Frame;
};
AddHandler navigation.FrameDocumentLoadFinished, Sub(s, e)
    Dim frame As IFrame = e.Frame
End Sub

此时,延迟脚本被执行,标记为 document_end 的内容脚本被注入到框架中。

自定义错误页面

要覆盖标准 Chromium 错误页面,请使用 ShowHttpErrorPageHandlerShowNetErrorPageHandler 处理程序,分别处理 HTTP 错误(如 404 Not Found)或网络错误(如 ERR_CONNECTION_REFUSED)。 请参阅以下示例:

HTTP 错误页面

browser.Navigation.ShowHttpErrorPageHandler =
    new Handler<ShowHttpErrorPageParameters, ShowHttpErrorPageResponse>(arg =>
    {
        string url = arg.Url;
        HttpStatusCode httpStatusCode = arg.HttpStatus;
        return ShowHttpErrorPageResponse.Show("HTTP Error web page:" + httpStatusCode);
    });
browser.Navigation.ShowHttpErrorPageHandler = 
    New Handler(Of ShowHttpErrorPageParameters, ShowHttpErrorPageResponse)(Function(arg)
        Dim url As String = arg.Url
        Dim httpStatusCode As HttpStatusCode = arg.HttpStatus
        Return ShowHttpErrorPageResponse.Show("HTTP Error web page:" & httpStatusCode)
    End Function)

网络错误页面

browser.Navigation.ShowNetErrorPageHandler = 
    new Handler<ShowNetErrorPageParameters, ShowNetErrorPageResponse>(arg =>
    {
        return ShowNetErrorPageResponse.Show("Network error web page");
    });
browser.Navigation.ShowNetErrorPageHandler = 
    New Handler(Of ShowNetErrorPageParameters, ShowNetErrorPageResponse)(Function(arg)
        Return ShowNetErrorPageResponse.Show("Network error web page")
    End Function)

服务器提供的自定义错误页面不会被这些处理程序拦截,并且无法使用此功能进行覆盖。 上述处理程序仅在覆盖 Chromium 默认错误页面时调用。

Go Top