.NET 多平台應用程式 UI (.NET MAUI) BlazorWebView 是一個控件,可讓您在 .NET MAUI 應用程式中裝載 Blazor Web 應用程式。 這些應用程式稱為 Blazor 混合式應用程式,可讓 Blazor Web 應用程式與平臺功能和 UI 控制件整合。 控件 BlazorWebView 可以新增至 .NET MAUI 應用程式的任何頁面,並指向 Blazor 應用程式的根目錄。 Razor 元件會在 .NET 程式中以原生方式執行,並將 Web UI 轉譯為內嵌的 Web 檢視控件。 在 .NET MAUI 中,Blazor 混合式應用程式可以在 .NET MAUI 支援的所有平台上執行。
BlazorWebView 會定義下列屬性:
-
HostPage的類型為
string?,定義了 Blazor Web 應用程式的根頁面。 -
RootComponents 的
RootComponentsCollection類型,指定可新增至控制元件的根組件集合。 -
StartPath,類型為
string,用於定義在 Blazor 元件完成載入後於 Blazor 瀏覽環境中的初始導航路徑。
類別 RootComponent 會定義下列屬性:
-
Selector的類型是
string?,其定義了 CSS 選擇器字串,以指定元件在文件中的應放置位置。 -
ComponentType屬於
Type?類型,定義了根元件的類型。 -
Parameters型別為
IDictionary<string, object?>?,表示一個可選的參數字典,用來傳遞至根元件。
此外, BlazorWebView 定義下列事件:
-
BlazorWebViewInitializing 會在 BlazorWebView 初始化之前引發,附帶有
BlazorWebViewInitializingEventArgs的物件。 此事件允許自訂化 BlazorWebView 組態。 -
BlazorWebViewInitialized 隨附
BlazorWebViewInitializedEventArgs的物件,在 BlazorWebView 初始化後,但在任何元件被轉譯之前引發。 此事件可擷取平臺特定的Web檢視實例。 - 當在BlazorWebView內按下超連結時,會引發具有隨附
UrlLoadingEventArgs物件的UrlLoading。 此事件可讓您自訂是否在BlazorWebView中開啟超連結、在外部應用程式中開啟,或者取消URL載入的嘗試。
現有的 Razor 元件 可以透過將程式代碼移至應用程式,或參考包含元件的現有類別庫或套件,在 .NET MAUI Blazor 應用程式中使用。 如需詳細資訊,請參閱 在 ASP.NET Core Blazor Hybrid 中重複使用 Razor 元件。
瀏覽器開發人員工具可用來檢查 .NET MAUI Blazor 應用程式。 如需詳細資訊,請參閱 搭配 ASP.NET Core Blazor Hybrid 使用瀏覽器開發人員工具。
注意
雖然 Visual Studio 會安裝開發 .NET MAUI Blazor 應用程式所需的所有工具,但 Windows 上的 .NET MAUI Blazor 應用程式的終端用戶必須安裝 WebView2 運行時間。
警告
在 Windows 上,使用安裝至 Program Files 目錄之 WebView2 型控制項的應用程式可能無法正確轉譯內容。 發生這種情況是因為 WebView2 嘗試將其快取和使用者資料檔案寫入應用程式的安裝目錄,該目錄在 中限制了寫入權限 Program Files。 若要解決此問題,請在初始化任何 WebView 控制項之前設定 WEBVIEW2_USER_DATA_FOLDER 環境變數:
#if WINDOWS
var userDataFolder = Path.Combine(FileSystem.AppDataDirectory, "WebView2");
Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", userDataFolder);
#endif
將此程式碼放在您的App.xaml.cs構造函式中,或在建立任何WebView控制項之前Platforms\Windows\App.xaml.cs。 這會指示 WebView2 使用使用者 AppData 目錄中的可寫入位置,而不是受限制的 Program Files 位置。
如需 Blazor 混合式應用程式的詳細資訊,請參閱 ASP.NET Core Blazor Hybrid。
瀏覽器引擎
WebView 在每個平台上使用不同的瀏覽器引擎來渲染網頁內容:
- Windows:使用 WebView2,其以 Microsoft Edge (Chromium) 瀏覽器引擎為基礎。 這提供了現代 Web 標準支援和與 Edge 瀏覽器的一致行為。
-
Android:使用
android.webkit.WebView,基於Chromium瀏覽器引擎。 具體版本取決於裝置上安裝的Android WebView系統元件。 -
iOS 和 Mac Catalyst:使用
WKWebView,它基於 Safari WebKit 瀏覽器引擎。 這與 iOS 和 macOS 上的 Safari 瀏覽器使用的引擎相同。
這些特定於平台的實作意味著 Web 內容在不同平台之間的呈現可能不同,並且某些特定於平台的 Web API 可能僅在某些平台上可用。 開發跨平台應用程式時,請在所有目標平台上測試您的網頁內容,以確保行為一致。
建立 .NET MAUI Blazor 應用程式
在 Visual Studio 中可以使用 .NET MAUI Blazor 應用程式範本 建立 .NET MAUI Blazor 應用程式:
此項目範本會建立可部署到 Android、iOS、macOS 和 Windows 的多目標 .NET MAUI Blazor 應用程式。 如需建立 .NET MAUI Blazor 應用程式的逐步指示,請參閱 建置 .NET MAUI Blazor 應用程式。
BlazorWebView由專案範本建立的內容定義於MainPage.xaml中,並指向 Blazor 應用程式的根目錄:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BlazorWebViewDemo"
x:Class="BlazorWebViewDemo.MainPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>
應用程式的根 Razor元件 位於 Main.razor中,Razor會編譯成應用程式根命名空間中名為 Main 的類型。 其餘的 Razor元件 位於 Pages 和 共用 專案資料夾中,且與預設 Blazor Web 樣本中使用的元件相同。 應用程式的靜態 Web 資產位於 wwwroot 資料夾中。
將 BlazorWebView 新增至現有的應用程式
將 BlazorWebView 新增至現有 .NET MAUI 應用程式的流程如下:
藉由在 CSPROJ 專案檔的第一行進行編輯,將 Razor SDK 和
Microsoft.NET.Sdk.Razor添加到您的專案中:<Project Sdk="Microsoft.NET.Sdk.Razor">需要Razor SDK,才能建置和封裝包含 Blazor 專案的 Razor 檔案的專案。
將應用程式的根 Razor元件 新增至專案。
將 Razor 元件 新增至名為 Pages 和 Shared 的項目資料夾。
將靜態 Web 資產新增至名為 wwwroot 的項目資料夾。
將任何可選的_Imports.razor檔案加入您的專案。
將 BlazorWebView 新增到您的 .NET MAUI 應用程式的畫面,並將它指向 Blazor 應用程式的根目錄:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MyBlazorApp" x:Class="MyBlazorApp.MainPage"> <BlazorWebView HostPage="wwwroot/index.html"> <BlazorWebView.RootComponents> <RootComponent Selector="#app" ComponentType="{x:Type local:Main}" /> </BlazorWebView.RootComponents> </BlazorWebView> </ContentPage>修改
MauiProgram類別的CreateMauiApp方法,將BlazorWebView控件註冊以供應用程式使用。 若要這樣做,請在 IServiceCollection 物件上呼叫AddMauiBlazorWebView方法,將元件 Web 檢視服務新增至服務集合:public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); }); builder.Services.AddMauiBlazorWebView(); #if DEBUG builder.Services.AddBlazorWebViewDeveloperTools(); #endif // Register any app services on the IServiceCollection object // e.g. builder.Services.AddSingleton<WeatherForecastService>(); return builder.Build(); } }當應用程式在偵錯組態中執行時,此程式代碼也會在基礎 WebView 控件上啟用開發人員工具。
從原生 UI 存取限定範圍的服務
BlazorWebView 有一個方法 TryDispatchAsync 能夠異步地呼叫指定的 Action<ServiceProvider>,並傳入在Razor 元件中可用的範圍服務。 這可讓來自原生 UI 的程式碼存取限定範圍的服務,例如 NavigationManager:
private async void OnMyMauiButtonClicked(object sender, EventArgs e)
{
var wasDispatchCalled = await blazorWebView.TryDispatchAsync(sp =>
{
var navMan = sp.GetRequiredService<NavigationManager>();
navMan.CallSomeNavigationApi(...);
});
if (!wasDispatchCalled)
{
// Consider what to do if it the dispatch fails - that's up to your app to decide.
}
}
診斷問題
BlazorWebView 內建記錄可協助您診斷 Blazor 混合式應用程式中的問題。 開啟此記錄有兩個步驟:
- 啟用 BlazorWebView 和相關元件來記錄診斷資訊。
- 設定記錄器,將記錄檔輸出寫入您可以檢視的位置。
如需記錄的詳細資訊,請參閱 在 C# 和 .NET 中記錄。
啟用 BlazorWebView 記錄
所有記錄組態都可以在相依性插入系統中作為服務註冊的一部分來執行。 若要在Microsoft.AspNetCore.Components.WebView命名空間下啟用BlazorWebView與相關元件的最大記錄,請將下列程式代碼新增到應用程式服務註冊的位置:
services.AddLogging(logging =>
{
logging.AddFilter("Microsoft.AspNetCore.Components.WebView", LogLevel.Trace);
});
或者,若要針對使用 Microsoft.Extensions.Logging的每個元件啟用最大記錄,您可以使用下列程式代碼:
services.AddLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Trace);
});
設定記錄輸出並檢視輸出
設定元件以寫入記錄資訊之後,您必須設定記錄器應寫入記錄檔的位置,然後檢視記錄輸出。
除錯記錄提供者使用Debug 語句進行輸出,且輸出可以在 Visual Studio 中查看。
若要設定偵錯記錄提供者,請先將 NuGet 套件的參考新增至專案中。 然後,藉由呼叫AddDebug擴充方法,將提供者註冊在您於上一步驟中新增的AddLogging呼叫中:
services.AddLogging(logging =>
{
logging.AddFilter("Microsoft.AspNetCore.Components.WebView", LogLevel.Trace);
logging.AddDebug();
});
當您從 Visual Studio 執行應用程式時(已啟用偵錯),您可以在 Visual Studio 的 [輸出 ] 視窗中檢視偵錯輸出。
在 iOS 上播放內嵌影片
若要在 iOS 上的 Blazor 混合式應用程式中播放內嵌影片,請在 BlazorWebView 中進行以下操作:
將 UrlLoadingStrategy 屬性設為
OpenInWebView。 這可以在事件的事件處理程式 UrlLoading 中完成:private void BlazorUrlLoading(object? sender, UrlLoadingEventArgs e) { #if IOS e.UrlLoadingStrategy = UrlLoadingStrategy.OpenInWebView; #endif }確定
AllowsInlineMediaPlayback物件中的Configuration屬性設定為true。 這可以在事件的事件處理程式 BlazorWebViewInitializing 中完成:private void BlazorWebViewInitializing(object? sender, BlazorWebViewInitializingEventArgs e) { #if IOS e.Configuration.AllowsInlineMediaPlayback = true; #endif }
在 Android 上解除死結
根據預設,BlazorWebView 會觸發並忽略底層 WebViewManager 的異步釋放。 這樣可減少Android上發生處置死結的可能性。
警告
這種「不用等待結果」的預設行為意味著在所有物件尚未完全釋放時,處置操作可以返回,這可能會導致應用程式的行為變更。 處置的項目部分是 Blazor 的內部類型,也包括應用程式中定義的類型,例如在應用程式的 BlazorWebView 部分所使用的範圍服務。
如要停用這項行為,您應該在您的AppContext類別中使用MauiProgram開關以封鎖處置:
static MauiProgram()
{
AppContext.SetSwitch("BlazorWebView.AndroidFireAndForgetAsync", false);
}
如果您的應用程式設定為透過這個開關在處置時進行封鎖,BlazorWebView 將執行同步過程中的異步處置,這表示它會封鎖線程,直到異步處置完成為止。 不過,如果處置需要在相同的線程上執行程序代碼,這可能會導致死結(因為線程在等候時遭到封鎖)。
使用舊版行為托管內容
在 BlazorWebView 中載入內容的預設行為已變更為 0.0.0.1。 用來裝載內容的內部 0.0.0.0 位址無法再運作,而且會導致 BlazorWebView 不會載入任何內容,並以空矩形呈現。
若要選擇使用該 0.0.0.0 地址,請將下列程式碼新增至您的 MauiProgram 類別:
static MauiProgram()
{
// Set this switch to use the LEGACY behavior of always using 0.0.0.0 to host BlazorWebView
AppContext.SetSwitch("BlazorWebView.AppHostAddressAlways0000", true);
}
攔截網路請求
BlazorWebView 可以攔截並回應從內嵌 Web 檢視內起始的 Web 請求。 這可以實現修改標頭、重定向請求或提供本地響應等場景。
若要攔截 Web 請求,請處理 WebResourceRequested 事件。 在事件處理常式中,將 Handled 設定為 true,且當您想要完全處理請求時,透過 SetResponse(statusCode, statusDescription, contentType, streamOrTaskOfStream) 提供回應。
blazorWebView.WebResourceRequested += (s, e) =>
{
// Example: short-circuit a specific API call with a local JSON response
if (e.Uri.ToString().Contains("/api/secure", StringComparison.OrdinalIgnoreCase))
{
e.Handled = true;
e.SetResponse(200, "OK", "application/json", GetLocalJsonStreamAsync());
return;
}
// Example: add an auth header for a particular host and allow normal processing
if (e.Uri.Host.Equals("api.contoso.com", StringComparison.OrdinalIgnoreCase))
{
e.RequestHeaders["Authorization"] = $"Bearer {GetToken()}";
// Don't set Handled; let the request proceed
}
};
private Task<Stream> GetLocalJsonStreamAsync()
{
// Return a stream containing JSON (for example from an embedded asset)
var json = Encoding.UTF8.GetBytes("{\"message\":\"Hello from local\"}");
return Task.FromResult<Stream>(new MemoryStream(json));
}
謹慎
WebResourceRequested回呼必須在 WebView 執行緒上同步執行。 如果您設定 Handled = true了 ,則必須立即致電 SetResponse 以提供回應。 針對非同步內容生成,請將Task<Stream>傳遞給SetResponse,以便讓 WebView 能夠在串流完成時繼續運作。
常見的模式包括:
- 插入或重寫特定主機的標題。
- 傳回本機檔案或記憶體內內容以進行離線或測試案例。
- 透過傳回 3xx 狀態並附加
Location標頭來重新導向到不同的 URI。