WebView

.NET Multi-platform App UI (.NET MAUI) WebView 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 WebView muestra.
  • 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 WebView muestra.
  • UserAgent, de tipo string, representa el agente de usuario. El valor predeterminado es el agente de usuario del explorador de plataforma subyacente o null 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 con estilo.

La propiedad Source se puede establecer en un objeto UrlWebViewSource o en un objeto HtmlWebViewSource, que ambos derivan de WebViewSource. UrlWebViewSource sirve para cargar una página web especificada con una dirección URL, mientras que un objeto HtmlWebViewSource sirve 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 la navegación.

Importante

WebView debe especificar sus propiedades HeightRequest y WidthRequest cuando están contenidos en HorizontalStackLayoutStackLayout o VerticalStackLayout. Si no puedes especificar estas propiedades, WebView no se representará.

Mostrar una página web

Para mostrar una página web remota, establece la propiedad Source en una 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 Apple Transport Security (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 de 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="&lt;HTML&gt;&lt;BODY&gt;&lt;H1&gt;.NET MAUI&lt;/H1&gt;&lt;P&gt;Welcome to WebView.&lt;/P&gt;&lt;/BODY&gt;&lt;HTML&gt;" />
    </WebView.Source>
</WebView>

En XAML, las cadenas HTML se pueden volver ilegibles debido a que se usan los símbolos < y > como caracteres de escape. 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. A continuación, el archivo se puede cargar desde el HTML insertado que se define en un objeto HtmlWebViewSource establecido 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 estilo 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.

Recargar 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 programática con los métodos GoBack y GoForward. Estos métodos habilitan la navegación de páginas apiladas 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áginas 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áginas. 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.
  • Navigated, que se genera cuando se completa la navegación de páginas. El objeto WebNavigatedEventArgs que acompaña al evento Navigated define una propiedad Result de tipo WebNavigationResult que indica el resultado de la 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. Sin embargo, la implementación de WebChromeClient proporcionada por .NET MAUI omite 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 enfoque, 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 .NET MAUI al usuario. El usuario solicita y aprueba los permisos de la aplicación .NET MAUI para toda la aplicación. El control WebView depende de la capacidad de las aplicaciones para acceder al hardware. Para ilustrar este concepto, piensa en una página web que solicita acceso a la cámara del dispositivo. Incluso si el control WebView aprueba esa solicitud, si la aplicación .NET MAUI no tuviera 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.

  1. 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" />
    
  2. En algún punto 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>();
    }
    
  3. 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 de MauiWebChromeClient e invalida el método OnPermissionRequest para interceptar las solicitudes de permisos de páginas web. Se comprueba cada elemento de permiso para ver si coincide con la constante de cadena PermissionRequest.ResourceVideoCapture, que representa la cámara. Si 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.

  4. Usa el método SetWebChromeClient en el control de WebView Android para establecer el cliente chrome en MyWebChromeClient. Los dos elementos siguientes muestran cómo puedes establecer el cliente chrome:

    • Dado un control WebView de .NET MAUI denominado theWebViewControl, 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étodo MauiProgram.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. Para establecer las cookies, agrega objetos Cookie a CookieContainer y luego 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 C# que realiza la llamada. Esta interoperabilidad se realiza con 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 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.

Puedes 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 de .NET MAUI y después modificarlo. A continuación, 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, se debe 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:

Se debe configurar MauiWKWebView con un objeto WKWebViewConfiguration antes de que se muestre WebView en la aplicación. Las ubicaciones adecuadas para hacerlo 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 dentro de 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 fábrica de controlador 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 WebView en iOS, consulta Configuración de WebView nativo en iOS y Mac Catalyst.

Inspección de un 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 la 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 WebView sea inspeccionable por las herramientas de desarrollo de Safari. Para más información sobre los controladores, consulta Controladores.

Para usar las herramientas de desarrollo de Safari con una aplicación Mac Catalyst:

  1. Abre Safari en el equipo Mac.
  2. En Safari, selecciona la casilla Safari > Settings >Advanced > Show Develop menu in menu bar.
  3. Ejecuta la aplicación .NET MAUI Mac Catalyst.
  4. En Safari, selecciona el menú Develop > {Nombre del dispositivo}, donde el marcador de posición {Device name} es el nombre del dispositivo, como Macbook Pro. A continuación, 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 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 más información, consulta Launcher.