.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,具有隨附
BlazorWebViewInitializingEventArgs的 物件,會在 初始化 之前 BlazorWebView 引發。 此事件會啟用組態的 BlazorWebView 自定義。 -
BlazorWebViewInitialized,具有隨附
BlazorWebViewInitializedEventArgs的 物件,會在 初始化 之後 BlazorWebView 引發,但在轉譯任何元件之前引發。 此事件可擷取平臺特定的Web檢視實例。 -
UrlLoading當在 內
UrlLoadingEventArgs按下超連結時,會引發具有隨附BlazorWebView物件的 。 此事件可讓您自定義是否在 中 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 應用程式
.NET MAUI Blazor 應用程式範本可以在 Visual Studio 中建立 .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 項目檔,
Microsoft.NET.Sdk.Razor將 Razor SDK 新增至您的專案:<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>CreateMauiApp修改 類別MauiProgram的 方法,以註冊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 記錄
所有記錄組態都可以在相依性插入系統中作為服務註冊的一部分來執行。 若要在 命名空間下BlazorWebView啟用和相關元件的記錄Microsoft.AspNetCore.Components.WebView上限,請將下列程式代碼新增至應用程式服務註冊的位置:
services.AddLogging(logging =>
{
logging.AddFilter("Microsoft.AspNetCore.Components.WebView", LogLevel.Trace);
});
或者,若要針對使用 Microsoft.Extensions.Logging的每個元件啟用最大記錄,您可以使用下列程式代碼:
services.AddLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Trace);
});
設定記錄輸出並檢視輸出
設定元件以寫入記錄資訊之後,您必須設定記錄器應寫入記錄檔的位置,然後檢視記錄輸出。
偵錯記錄提供者會使用 Debug 語句寫入輸出,而且可以從 Visual Studio 檢視輸出。
若要設定偵 錯 記錄提供者,請先將專案中的 Microsoft.Extensions.Logging.Debug 參考新增至 NuGet 套件。 然後,藉由呼叫AddLogging擴充方法,在上一個步驟中新增的 呼叫AddDebug內註冊提供者:
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);
}
攔截 Web 請求
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 以提供回應。 針對非同步內容產生,請將 a Task<Stream> 傳遞給 SetResponse ,讓 WebView 可以在資料流程完成時繼續。
常見的模式包括:
- 插入或重寫特定主機的標頭。
- 傳回本機檔案或記憶體內內容以進行離線或測試案例。
- 透過傳回帶有標頭的
Location3xx 狀態來重新導向到不同的 URI。