title | description | ms.date | zone_pivot_groups |
---|---|---|---|
WebView |
This article explains how to use the .NET MAUI WebView to display remote web pages, local HTML files, and HTML strings. |
10/11/2022 |
devices-deployment |
The .NET Multi-platform App UI (.NET MAUI) xref:Microsoft.Maui.Controls.WebView displays remote web pages, local HTML files, and HTML strings, in an app. The content displayed a xref:Microsoft.Maui.Controls.WebView includes support for Cascading Style Sheets (CSS), and JavaScript. By default, .NET MAUI projects include the platform permissions required for a xref:Microsoft.Maui.Controls.WebView to display a remote web page.
xref:Microsoft.Maui.Controls.WebView defines the following properties:
::: moniker range="=net-maui-7.0"
Cookies
, of typeCookieContainer
, provides storage for a collection of cookies.CanGoBack
, of typebool
, indicates whether the user can navigate to previous pages. This is a read-only property.CanGoForward
, of typebool
, indicates whether the user can navigate forward. This is a read-only property.Source
, of typeWebViewSource
, represents the location that the xref:Microsoft.Maui.Controls.WebView displays.
::: moniker-end
::: moniker range=">=net-maui-8.0"
Cookies
, of typeCookieContainer
, provides storage for a collection of cookies.CanGoBack
, of typebool
, indicates whether the user can navigate to previous pages. This is a read-only property.CanGoForward
, of typebool
, indicates whether the user can navigate forward. This is a read-only property.Source
, of typeWebViewSource
, represents the location that the xref:Microsoft.Maui.Controls.WebView displays.UserAgent
, of typestring
, represents the user agent. The default value is the user agent of the underlying platform browser, ornull
if it can't be determined.
::: moniker-end
These properties are backed by xref:Microsoft.Maui.Controls.BindableProperty objects, which means that they can be targets of data bindings, and styled.
The Source
property can be set to an UrlWebViewSource
object or a HtmlWebViewSource
object, which both derive from WebViewSource
. A UrlWebViewSource
is used for loading a web page specified with a URL, while a HtmlWebViewSource
object is used for loading a local HTML file, or local HTML.
xref:Microsoft.Maui.Controls.WebView defines a Navigating
event that's raised when page navigation starts, and a Navigated
event that's raised when page navigation completes. The WebNavigatingEventArgs
object that accompanies the Navigating
event defines a Cancel
property of type bool
that can be used to cancel navigation. The WebNavigatedEventArgs
object that accompanies the Navigated
event defines a Result
property of type WebNavigationResult
that indicates the navigation result.
Important
A xref:Microsoft.Maui.Controls.WebView must specify its xref:Microsoft.Maui.Controls.VisualElement.HeightRequest and xref:Microsoft.Maui.Controls.VisualElement.WidthRequest properties when contained in a xref:Microsoft.Maui.Controls.HorizontalStackLayout, xref:Microsoft.Maui.Controls.StackLayout, or xref:Microsoft.Maui.Controls.VerticalStackLayout. If you fail to specify these properties, the xref:Microsoft.Maui.Controls.WebView will not render.
To display a remote web page, set the Source
property to a string
that specifies the URI:
<WebView Source="https://learn.microsoft.com/dotnet/maui" />
The equivalent C# code is:
WebView webvView = new WebView
{
Source = "https://learn.microsoft.com/dotnet/maui"
};
URIs must be fully formed with the protocol specified.
Note
Despite the Source
property being of type WebViewSource
, the property can be set to a string-based URI. This is because .NET MAUI includes a type converter, and an implicit conversion operator, that converts the string-based URI to a UrlWebViewSource
object.
:::zone pivot="devices-windows"
:::zone-end
:::zone pivot="devices-ios, devices-maccatalyst"
Since version 9, iOS will only allow your app to communicate with secure servers. An app has to opt into enabling communication with insecure servers.
The following Info.plist configuration shows how to enable a specific domain to bypass Apple Transport Security (ATS) requirements:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>mydomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
It's best practice to only enable specific domains to bypass ATS, allowing you to use trusted sites while benefitting from additional security on untrusted domains.
The following Info.plist configuration shows how to disable ATS for an app:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Important
If your app requires a connection to an insecure website, you should always enter the domain as an exception using the NSExceptionDomains
key instead of turning ATS off completely using the NSAllowsArbitraryLoads
key.
:::zone-end
To display inline HTML, set the Source
property to a HtmlWebViewSource
object:
<WebView>
<WebView.Source>
<HtmlWebViewSource Html="<HTML><BODY><H1>.NET MAUI</H1><P>Welcome to WebView.</P></BODY><HTML>" />
</WebView.Source>
</WebView>
In XAML, HTML strings can become unreadable due to escaping the <
and >
symbols. Therefore, for greater readability the HTML can be inlined in a CDATA
section:
<WebView>
<WebView.Source>
<HtmlWebViewSource>
<HtmlWebViewSource.Html>
<![CDATA[
<HTML>
<BODY>
<H1>.NET MAUI</H1>
<P>Welcome to WebView.</P>
</BODY>
</HTML>
]]>
</HtmlWebViewSource.Html>
</HtmlWebViewSource>
</WebView.Source>
</WebView>
The equivalent C# code is:
WebView webView = new WebView
{
Source = new HtmlWebViewSource
{
Html = @"<HTML><BODY><H1>.NET MAUI</H1><P>Welcome to WebView.</P></BODY></HTML>"
}
};
To display a local HTML file, add the file to the Resources\Raw folder of your app project and set its build action to MauiAsset. Then, the file can be loaded from inline HTML that's defined in a HtmlWebViewSource
object that's set as the value of the Source
property:
<WebView>
<WebView.Source>
<HtmlWebViewSource>
<HtmlWebViewSource.Html>
<![CDATA[
<html>
<head>
</head>
<body>
<h1>.NET MAUI</h1>
<p>The CSS and image are loaded from local files!</p>
<p><a href="localfile.html">next page</a></p>
</body>
</html>
]]>
</HtmlWebViewSource.Html>
</HtmlWebViewSource>
</WebView.Source>
</WebView>
The local HTML file can load Cascading Style Sheets (CSS), JavaScript, and images, if they've also been added to your app project with the MauiAsset build action.
For more information about raw assets, see Raw assets.
xref:Microsoft.Maui.Controls.WebView has a Reload
method that can be called to reload its source:
WebView webView = new WebView();
...
webView.Reload();
xref:Microsoft.Maui.Controls.WebView supports programmatic navigation with the GoBack
and GoForward
methods. These methods enable navigation through the xref:Microsoft.Maui.Controls.WebView page stack, and should only be called after inspecting the values of the CanGoBack
and CanGoForward
properties:
WebView webView = new WebView();
...
// Go backwards, if allowed.
if (webView.CanGoBack)
{
webView.GoBack();
}
// Go forwards, if allowed.
if (webView.CanGoForward)
{
webView.GoForward();
}
When page navigation occurs in a xref:Microsoft.Maui.Controls.WebView, either initiated programmatically or by the user, the following events occur:
Navigating
, which is raised when page navigation starts. TheWebNavigatingEventArgs
object that accompanies theNavigating
event defines aCancel
property of typebool
that can be used to cancel navigation.Navigated
, which is raised when page navigation completes. TheWebNavigatedEventArgs
object that accompanies theNavigated
event defines aResult
property of typeWebNavigationResult
that indicates the navigation result.
:::zone pivot="devices-android"
When browsing to a page that requests access to the device's recording hardware, such as the camera or microphone, permission must be granted by the xref:Microsoft.Maui.Controls.WebView control. The WebView
control uses the xref:Android.Webkit.WebChromeClient?displayProperty=fullName type on Android to react to permission requests. However, the WebChromeClient
implementation provided by .NET MAUI ignores permission requests. You must create a new type that inherits from MauiWebChromeClient
and approves the permission requests.
Important
Customizing the WebView
to approve permission requests, using this approach, requires Android API 26 or later.
The permission requests from a web page to the WebView
control are different than permission requests from the .NET MAUI app to the user. .NET MAUI app permissions are requested and approved by the user, for the whole app. The WebView
control is dependent on the apps ability to access the hardware. To illustrate this concept, consider a web page that requests access to the device's camera. Even if that request is approved by the WebView
control, yet the .NET MAUI app didn't have approval by the user to access the camera, the web page wouldn't be able to access the camera.
The following steps demonstrate how to intercept permission requests from the WebView
control to use the camera. If you are trying to use the microphone, the steps would be similar except that you would use microphone-related permissions instead of camera-related permissions.
-
First, add the required app permissions to the Android manifest. Open the Platforms/Android/AndroidManifest.xml file and add the following in the
manifest
node:<uses-permission android:name="android.permission.CAMERA" />
-
At some point in your app, such as when the page containing a
WebView
control is loaded, request permission from the user to allow the app access to the camera.private async Task RequestCameraPermission() { PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.Camera>(); if (status != PermissionStatus.Granted) await Permissions.RequestAsync<Permissions.Camera>(); }
-
Add the following class to the Platforms/Android folder, changing the root namespace to match your project's namespace:
using Android.Webkit; using Microsoft.Maui.Handlers; using Microsoft.Maui.Platform; namespace MauiAppWebViewHandlers.Platforms.Android; internal class MyWebChromeClient: MauiWebChromeClient { public MyWebChromeClient(IWebViewHandler handler) : base(handler) { } public override void OnPermissionRequest(PermissionRequest request) { // Process each request foreach (var resource in request.GetResources()) { // Check if the web page is requesting permission to the camera if (resource.Equals(PermissionRequest.ResourceVideoCapture, StringComparison.OrdinalIgnoreCase)) { // Get the status of the .NET MAUI app's access to the camera PermissionStatus status = Permissions.CheckStatusAsync<Permissions.Camera>().Result; // Deny the web page's request if the app's access to the camera is not "Granted" if (status != PermissionStatus.Granted) request.Deny(); else request.Grant(request.GetResources()); return; } } base.OnPermissionRequest(request); } }
In the previous snippet, the
MyWebChromeClient
class inherits fromMauiWebChromeClient
, and overrides theOnPermissionRequest
method to intercept web page permission requests. Each permission item is checked to see if it matches thePermissionRequest.ResourceVideoCapture
string constant, which represents the camera. If a camera permission is matched, the code checks to see if the app has permission to use the camera. If it has permission, the web page's request is granted. -
Use the xref:Android.Webkit.WebView.SetWebChromeClient%2A method on the Android's
WebView
control to set the chrome client toMyWebChromeClient
. The following two items demonstrate how you can set the chrome client:-
Given a .NET MAUI
WebView
control namedtheWebViewControl
, you can set the chrome client directly on the platform view, which is the Android control:((IWebViewHandler)theWebViewControl.Handler).PlatformView.SetWebChromeClient(new MyWebChromeClient((IWebViewHandler)theWebViewControl.Handler));
-
You can also use handler property mapping to force all
WebView
controls to use your chrome client. For more information, see Handlers.The following snippet's
CustomizeWebViewHandler
method should be called when the app starts, such as in theMauiProgram.CreateMauiApp
method.private static void CustomizeWebViewHandler() { #if ANDROID26_0_OR_GREATER Microsoft.Maui.Handlers.WebViewHandler.Mapper.ModifyMapping( nameof(Android.Webkit.WebView.WebChromeClient), (handler, view, args) => handler.PlatformView.SetWebChromeClient(new MyWebChromeClient(handler))); #endif }
-
:::zone-end
Cookies can be set on a xref:Microsoft.Maui.Controls.WebView so that they are sent with the web request to the specified URL. Set the cookies by adding Cookie
objects to a CookieContainer
, and then set the container as the value of the WebView.Cookies
bindable property. The following code shows an example:
using System.Net;
CookieContainer cookieContainer = new CookieContainer();
Uri uri = new Uri("https://learn.microsoft.com/dotnet/maui", UriKind.RelativeOrAbsolute);
Cookie cookie = new Cookie
{
Name = "DotNetMAUICookie",
Expires = DateTime.Now.AddDays(1),
Value = "My cookie",
Domain = uri.Host,
Path = "/"
};
cookieContainer.Add(uri, cookie);
webView.Cookies = cookieContainer;
webView.Source = new UrlWebViewSource { Url = uri.ToString() };
In this example, a single Cookie
is added to the CookieContainer
object, which is then set as the value of the WebView.Cookies
property. When the xref:Microsoft.Maui.Controls.WebView sends a web request to the specified URL, the cookie is sent with the request.
xref:Microsoft.Maui.Controls.WebView includes the ability to invoke a JavaScript function from C# and return any result to the calling C# code. This interop is accomplished with the EvaluateJavaScriptAsync
method, which is shown in the following example:
Entry numberEntry = new Entry { Text = "5" };
Label resultLabel = new Label();
WebView webView = new WebView();
...
int number = int.Parse(numberEntry.Text);
string result = await webView.EvaluateJavaScriptAsync($"factorial({number})");
resultLabel.Text = $"Factorial of {number} is {result}.";
The WebView.EvaluateJavaScriptAsync
method evaluates the JavaScript that's specified as the argument, and returns any result as a string
. In this example, the factorial
JavaScript function is invoked, which returns the factorial of number
as a result. This JavaScript function is defined in the local HTML file that the xref:Microsoft.Maui.Controls.WebView loads, and is shown in the following example:
<html>
<body>
<script type="text/javascript">
function factorial(num) {
if (num === 0 || num === 1)
return 1;
for (var i = num - 1; i >= 1; i--) {
num *= i;
}
return num;
}
</script>
</body>
</html>
:::zone pivot="devices-ios, devices-maccatalyst"
The native xref:Microsoft.Maui.Controls.WebView control is a MauiWKWebView
on iOS and Mac Catalyst, which derives from WKWebView
. One of the MauiWKWebView
constructor overloads enables a WKWebViewConfiguration
object to be specified, which provides information about how to configure the WKWebView
object. Typical configurations include setting the user agent, specifying cookies to make available to your web content, and injecting custom scripts into your web content.
You can create a WKWebViewConfiguration
object in your app, and then configure its properties as required. Alternatively, you can call the static MauiWKWebView.CreateConfiguration
method to retrieve .NET MAUI's WKWebViewConfiguration
object and then modify it. The WKWebViewConfiguration
object can then be passed to the MauiWKWebView
constructor overload by modifying the factory method that WebViewHandler
uses to create its native control on each platform:
#if IOS || MACCATALYST
using WebKit;
using CoreGraphics;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
#endif
...
#if IOS || MACCATALYST
WKWebViewConfiguration config = MauiWKWebView.CreateConfiguration();
config.ApplicationNameForUserAgent = "MyProduct/1.0.0";
WebViewHandler.PlatformViewFactory =
handler => new MauiWKWebView(CGRect.Empty, (WebViewHandler)handler, config);
#endif
Note
You should configure MauiWKWebView
with a WKWebViewConfiguration
object before a xref:Microsoft.Maui.Controls.WebView is displayed in your app. Suitable locations to do this are in your app's startup path, such as in MauiProgram.cs or App.xaml.cs.
:::zone-end
:::zone pivot="devices-maccatalyst"
To use Safari developer tools to inspect the contents of a WebView
on Mac Catalyst requires you to add the com.apple.security.get-task-allow
key, of type Boolean
, to the entitlements file of your app for its debug build. For more information about entitlements, see Entitlements.
To add an entitlements file to your .NET MAUI app project, add a new XML file named Entitlements.Debug.plist to the Platforms\MacCatalyst folder of your app project. Then add the following XML to the file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.get-task-allow</key>
<true/>
</dict>
</plist>
To configure your app to consume this entitlements file, add the following <PropertyGroup>
node to your app's project file as a child of the <Project>
node:
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst' and '$(Configuration)' == 'Debug'">
<CodeSignEntitlements>Platforms/MacCatalyst/Entitlements.Debug.plist</CodeSignEntitlements>
</PropertyGroup>
This configuration ensures that the entitlements file is only processed for debug builds on Mac Catalyst.
:::zone-end
It's possible to open a URI in the system web browser with the Launcher
class, which is provided by Microsoft.Maui.Essentials
. Call the launcher's OpenAsync
method and pass in a string
or Uri
argument that represents the URI to open:
await Launcher.OpenAsync("https://learn.microsoft.com/dotnet/maui");
For more information, see Launcher.