WebView
WebView de .NET Multi-platform App UI (.NET MAUI) muestra páginas web remotas, archivos HTML locales y cadenas HTML, en una aplicación. El contenido mostrado como WebView incluye compatibilidad con hojas de estilos en cascada (CSS) y JavaScript. De forma predeterminada, los proyectos de .NET MAUI incluyen los permisos de plataforma necesarios para que WebView muestre una página web remota.
WebView define las siguientes propiedades:
- Cookies, de tipo
CookieContainer
, proporciona almacenamiento para una colección de cookies. - CanGoBack de tipo
bool
, indica si el usuario puede navegar a páginas anteriores. Se trata de una propiedad de solo lectura. - CanGoForward, de tipo
bool
, indica si el usuario puede navegar hacia delante. Se trata de una propiedad de solo lectura. - Source, de tipo
WebViewSource
, representa la ubicación que muestra WebView. - UserAgent, de tipo
string
, representa el agente de usuario. El valor predeterminado es el agente de usuario del explorador de plataforma subyacente, onull
si no se puede determinar.
Estas propiedades están respaldadas por objetos BindableProperty, lo que significa que pueden ser destinos de los enlaces de datos, y que se les puede aplicar un estilo.
La propiedad Source
se puede establecer en un objeto UrlWebViewSource
o en un objeto HtmlWebViewSource
, que ambos derivan de WebViewSource
. Un UrlWebViewSource
se usa para cargar una página web especificada con una dirección URL, mientras que se usa un objeto HtmlWebViewSource
para cargar un archivo HTML local o HTML local.
WebView define un evento Navigating
que se genera cuando se inicia la navegación de página y un evento Navigated
que se genera cuando se completa la navegación de página. El objeto WebNavigatingEventArgs
que acompaña al evento Navigating
define una propiedad Cancel
de tipo bool
que se puede usar para cancelar la navegación. El objeto WebNavigatedEventArgs
que acompaña al evento Navigated
define una propiedad Result
de tipo WebNavigationResult
que indica el resultado de navegación.
WebView define los siguientes eventos:
Navigating
, que se genera cuando la navegación se inicia. El objetoWebNavigatingEventArgs
que acompaña este evento define una propiedadCancel
de tipobool
que se puede usar para cancelar la navegación.Navigated
, que se genera cuando se completa la navegación de página. El objetoWebNavigatedEventArgs
que acompaña este evento define una propiedadResult
de tipoWebNavigationResult
que indica el resultado de navegación.ProcessTerminated
, que se genera cuando un proceso de WebView finaliza inesperadamente. El objetoWebViewProcessTerminatedEventArgs
que acompaña a este evento define propiedades específicas de la plataforma que indican por qué se produjo un error en el proceso.
Importante
Un WebView debe especificar sus propiedades HeightRequest y WidthRequest cuando se encuentran en HorizontalStackLayout, StackLayout o VerticalStackLayout. Si no pueden especificar estas propiedades, WebView no se representará.
Mostrar una página web
Para mostrar una página web remota, establece la propiedad Source
en un string
que especifique el URI:
<WebView Source="https://learn.microsoft.com/dotnet/maui" />
El código de C# equivalente es el siguiente:
WebView webvView = new WebView
{
Source = "https://learn.microsoft.com/dotnet/maui"
};
Los URI deben tener un formato completo con el protocolo especificado.
Nota:
A pesar de que la propiedad Source
es de tipo WebViewSource
, la propiedad se puede establecer en un URI basado en cadenas. Esto se debe a que .NET MAUI incluye un convertidor de tipos y un operador de conversión implícito, que convierte el URI basado en cadenas en un objeto UrlWebViewSource
.
Configuración de la Seguridad de transporte de aplicación en iOS y Mac Catalyst
Desde la versión 9, iOS solo permitirá que la aplicación se comunique con servidores seguros. Una aplicación tiene que optar por habilitar la comunicación con servidores no seguros.
La siguiente configuración de Info.plist muestra cómo habilitar un dominio específico para omitir los requisitos de Seguridad de transporte de aplicación (ATS):
<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>
Se recomienda habilitar solo dominios específicos para omitir ATS, lo que te permite usar sitios de confianza al tiempo que te beneficias de la seguridad adicional en dominios que no son de confianza.
La siguiente configuración Info.plist muestra cómo deshabilitar ATS para una aplicación:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Importante
Si la aplicación requiere una conexión a un sitio web no seguro, siempre debes escribir el dominio como una excepción mediante la clave NSExceptionDomains
en lugar de desactivar ATS completamente con la clave NSAllowsArbitraryLoads
.
Mostrar HTML local
Para mostrar HTML insertado, establece la propiedad Source
en un objeto HtmlWebViewSource
:
<WebView>
<WebView.Source>
<HtmlWebViewSource Html="<HTML><BODY><H1>.NET MAUI</H1><P>Welcome to WebView.</P></BODY><HTML>" />
</WebView.Source>
</WebView>
En XAML, las cadenas HTML se pueden volver ilegibles debido a que se escapan los símbolos <
y >
. Por lo tanto, para mejorar la legibilidad, el código HTML se puede insertar en una sección CDATA
:
<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>
El código de C# equivalente es el siguiente:
WebView webView = new WebView
{
Source = new HtmlWebViewSource
{
Html = @"<HTML><BODY><H1>.NET MAUI</H1><P>Welcome to WebView.</P></BODY></HTML>"
}
};
Mostrar un archivo HTML local
Para mostrar un archivo HTML local, agrega el archivo a la carpeta Resources\Raw del proyecto de aplicación y establece su acción de compilación en MauiAsset. Después, el archivo se puede cargar desde HTML insertado que se define en un objeto HtmlWebViewSource
que se establece como el valor de la propiedad Source
:
<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>
El archivo HTML local puede cargar hojas de estilos en cascada (CSS), JavaScript e imágenes, si también se han agregado al proyecto de aplicación con la acción de compilación MauiAsset.
Para obtener más información sobre recursos sin procesar, consulta Recursos sin procesar.
Volver a cargar contenido
WebView tiene un método Reload
al que se puede llamar para recargar su origen:
WebView webView = new WebView();
...
webView.Reload();
Cuando se invoca el método Reload
, se desencadena el evento ReloadRequested
, lo que indica que se ha realizado una solicitud para recargar el contenido actual.
Realización de la navegación
WebView admite la navegación mediante programación con los métodos GoBack
y GoForward
. Estos métodos habilitan la navegación a través de la pila de páginas WebView y solo deben llamarse después de inspeccionar los valores de las propiedades CanGoBack
y CanGoForward
:
WebView webView = new WebView();
...
// Go backwards, if allowed.
if (webView.CanGoBack)
{
webView.GoBack();
}
// Go forwards, if allowed.
if (webView.CanGoForward)
{
webView.GoForward();
}
Cuando la navegación de página se produce en WebView, ya sea iniciada mediante programación o por el usuario, se producen los siguientes eventos:
Navigating
, que se genera cuando se inicia la navegación de página. El objetoWebNavigatingEventArgs
que acompaña al eventoNavigating
define una propiedadCancel
de tipobool
que se puede usar para cancelar la navegación.Navigated
, que se genera cuando se completa la navegación de página. El objetoWebNavigatedEventArgs
que acompaña al eventoNavigated
define una propiedadResult
de tipoWebNavigationResult
que indica el resultado de navegación.
Control de permisos en Android
Al navegar a una página que solicita acceso al hardware de grabación del dispositivo, como la cámara o el micrófono, el control WebView debe conceder el permiso. El control WebView
usa el tipo Android.Webkit.WebChromeClient en Android para reaccionar a las solicitudes de permisos. Pero la implementación WebChromeClient
proporcionada por .NET MAUI ignora las solicitudes de permisos. Debes crear un nuevo tipo que herede de MauiWebChromeClient
y apruebe las solicitudes de permisos.
Importante
La personalización de WebView
para aprobar solicitudes de permisos, con este método, requiere la API de Android 26 o posterior.
Las solicitudes de permisos de una página web al control WebView
son diferentes de las solicitudes de permisos de la aplicación MAUI de .NET al usuario. El usuario solicita y aprueba los permisos de la aplicación MAUI de .NET para toda la aplicación. El control WebView
depende de la capacidad de las aplicaciones para acceder al hardware. Para ilustrar este concepto, considera una página web que solicita acceso a la cámara del dispositivo. Incluso si el control WebView
aprueba esa solicitud, pero la aplicación MAUI de .NET no tenía la aprobación del usuario para acceder a la cámara, la página web no podría acceder a la cámara.
En los pasos siguientes se muestra cómo interceptar las solicitudes de permiso del control WebView
para usar la cámara. Si intentas usar el micrófono, los pasos serían similares, excepto que usarías permisos relacionados con el micrófono en lugar de permisos relacionados con la cámara.
En primer lugar, agrega los permisos de aplicación necesarios al manifiesto de Android. Abre el archivo Platforms/Android/AndroidManifest.xml y agrega lo siguiente en el nodo
manifest
:<uses-permission android:name="android.permission.CAMERA" />
En algún momento de la aplicación, como cuando se carga la página que contiene un control
WebView
, solicita permiso al usuario para permitir que la aplicación acceda a la cámara.private async Task RequestCameraPermission() { PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.Camera>(); if (status != PermissionStatus.Granted) await Permissions.RequestAsync<Permissions.Camera>(); }
Agrega la siguiente clase a la carpeta Platforms/Android y cambia el espacio de nombres raíz para que coincida con el espacio de nombres del proyecto:
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); } }
En el fragmento de código anterior, la clase
MyWebChromeClient
hereda deMauiWebChromeClient
e invalida el métodoOnPermissionRequest
para interceptar las solicitudes de permisos de página web. Cada elemento de permiso se comprueba para ver si coincide con la constante de cadenaPermissionRequest.ResourceVideoCapture
, que representa la cámara. Si se coincide con un permiso de cámara, el código comprueba si la aplicación tiene permiso para usar la cámara. Si tiene permiso, se concede la solicitud de la página web.Usa el método SetWebChromeClient en el control
WebView
de Android para establecer el cliente chrome enMyWebChromeClient
. Los dos elementos siguientes muestran cómo puedes establecer el cliente chrome:Dado un control
WebView
MAUI de .NET denominadotheWebViewControl
, puedes establecer el cliente chrome directamente en la vista de plataforma, que es el control Android:((IWebViewHandler)theWebViewControl.Handler).PlatformView.SetWebChromeClient(new MyWebChromeClient((IWebViewHandler)theWebViewControl.Handler));
También puedes usar la asignación de propiedades del controlador para forzar que todos los controles
WebView
usen el cliente chrome. Para obtener más información, consulta Controladores.Se debe llamar al método
CustomizeWebViewHandler
del fragmento de código siguiente cuando se inicia la aplicación, como en el métodoMauiProgram.CreateMauiApp
.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 }
Establecimiento de cookies
Las cookies se pueden establecer en WebView para que se envíen con la solicitud web a la dirección URL especificada. Establece las cookies agregando objetos Cookie
a CookieContainer
y, después, establece el contenedor como el valor de la propiedad enlazable WebView.Cookies
. El código siguiente muestra un ejemplo:
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() };
En este ejemplo, se agrega un único Cookie
al objeto CookieContainer
, que luego se establece como el valor de la propiedad WebView.Cookies
. Cuando WebView envía una solicitud web a la dirección URL especificada, la cookie se envía con la solicitud.
Invocación de JavaScript
WebView incluye la capacidad de invocar una función de JavaScript desde C# y devolver cualquier resultado al código de C# que realiza la llamada. Esto puede realizarse invalidando el método EvaluateJavaScriptAsync
, que se muestra en el siguiente ejemplo:
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}.";
El método WebView.EvaluateJavaScriptAsync
evalúa el JavaScript especificado como argumento y devuelve cualquier resultado como string
. En este ejemplo, se invoca la función factorial
de JavaScript, que devuelve el factorial de number
como resultado. Esta función de JavaScript se define en el archivo HTML local que carga WebView y se muestra en el ejemplo siguiente:
<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>
Configuración de WebView nativo en iOS y Mac Catalyst
El control nativo WebView es un MauiWKWebView
en iOS y Mac Catalyst, que deriva de WKWebView
. Una de las sobrecargas del constructor MauiWKWebView
permite especificar un objeto WKWebViewConfiguration
, que proporciona información sobre cómo configurar el objeto WKWebView
. Las configuraciones típicas incluyen establecer el agente de usuario, especificar cookies para que estén disponibles para el contenido web e insertar scripts personalizados en el contenido web.
Puede crear un objeto WKWebViewConfiguration
en la aplicación y después configurar sus propiedades según sea necesario. De manera alternativa, se puede llamar al método estático MauiWKWebView.CreateConfiguration
para recuperar el objeto WKWebViewConfiguration
.NET MAUI y después modificarlo. Luego, el objeto WKWebViewConfiguration
se puede especificar como argumento para la sobrecarga del constructor MauiWKWebView
.
Dado que la configuración del WebView nativo no se puede cambiar en iOS y Mac Catalyst una vez creada la vista de plataforma del controlador, deberás crear un delegado de fábrica de controlador personalizado para modificarlo:
#if IOS || MACCATALYST
using WebKit;
using CoreGraphics;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
#endif
...
#if IOS || MACCATALYST
Microsoft.Maui.Handlers.WebViewHandler.PlatformViewFactory = (handler) =>
{
WKWebViewConfiguration config = MauiWKWebView.CreateConfiguration();
config.ApplicationNameForUserAgent = "MyProduct/1.0.0";
return new MauiWKWebView(CGRect.Empty, (WebViewHandler)handler, config);
};
#endif
Nota:
Debes configurar MauiWKWebView
con un objeto WKWebViewConfiguration
antes de que se muestre WebView en tu aplicación. Las ubicaciones adecuadas para hacer esto se encuentran en la ruta de inicio de la aplicación, como en MauiProgram.cs o App.xaml.cs.
Establecer preferencias de reproducción multimedia en iOS y Mac Catalyst
La reproducción multimedia insertada de vídeo HTML5, incluida la reproducción automática y la imagen en la imagen, está habilitada de forma predeterminada para WebView en iOS y Mac Catalyst. Para cambiar este valor predeterminado o establecer otras preferencias de reproducción multimedia, debes crear un delegado de generador de controladores personalizado, ya que las preferencias de reproducción multimedia no se pueden cambiar una vez creada la vista de plataforma del controlador. El código siguiente muestra un ejemplo de esto:
#if IOS || MACCATALYST
using WebKit;
using CoreGraphics;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
#endif
...
#if IOS || MACCATALYST
Microsoft.Maui.Handlers.WebViewHandler.PlatformViewFactory = (handler) =>
{
WKWebViewConfiguration config = MauiWKWebView.CreateConfiguration();
// True to play HTML5 videos inliine, false to use the native full-screen controller.
config.AllowsInlineMediaPlayback = false;
// True to play videos over AirPlay, otherwise false.
config.AllowsAirPlayForMediaPlayback = false;
// True to let HTML5 videos play Picture in Picture.
config.AllowsPictureInPictureMediaPlayback = false;
// Media types that require a user gesture to begin playing.
config.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.All;
return new MauiWKWebView(CGRect.Empty, (WebViewHandler)handler, config);
};
#endif
Para obtener más información sobre cómo configurar un WebView en iOS, consulta Configuración de WebView nativo en iOS y Mac Catalyst.
Inspección de WebView en Mac Catalyst
Para usar las herramientas de desarrollo de Safari para inspeccionar el contenido de WebView en Mac Catalyst, agrega el código siguiente a tu aplicación:
#if MACCATALYST
Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping("Inspect", (handler, view) =>
{
if (OperatingSystem.IsMacCatalystVersionAtLeast(16, 6))
handler.PlatformView.Inspectable = true;
});
#endif
Este código personaliza el asignador de propiedades para WebViewHandler
en Mac Catalyst para hacer que el contenido de WebView sea inspeccionable por las herramientas de desarrollo de Safari. Para obtener más información sobre el uso de los controladores de eventos, consulta Información general sobre controladores de eventos.
Para usar las herramientas para desarrolladores de Safari con una aplicación Mac Catalyst:
- Abre Safari en tu Mac.
- En Safari, selecciona la casilla Safari>Preferencias>Avanzado>Mostrar el menú Desarrollo en la barra de menús.
- Ejecuta tu aplicación Mac Catalyst.de .NET MAUI.
- En Safari, selecciona el menú Desarrollar > {Nombre del dispositivo}, donde el marcador de posición
{Device name}
es el nombre del dispositivo, comoMacbook Pro
. Después, selecciona la entrada en el nombre de la aplicación, que también resaltará la aplicación en ejecución. Esto hará que aparezca la ventana del Inspector web
Utiliza el explorador del sistema.
Es posible abrir un URI en el explorador web del sistema con la clase Launcher
, que Microsoft.Maui.Essentials
proporciona. Llama al método OpenAsync
del iniciador y pasa un argumento string
o Uri
que representa el URI que se va a abrir:
await Launcher.OpenAsync("https://learn.microsoft.com/dotnet/maui");
Para obtener más información, consulta Launcher.