Share via


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, 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 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.

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="&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 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 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ágina. El objeto WebNavigatedEventArgs que acompaña al evento Navigated define una propiedad Result de tipo WebNavigationResult 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.

  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 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>();
    }
    
  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ágina web. Cada elemento de permiso se comprueba para ver si coincide con la constante de cadena PermissionRequest.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.

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

    • Dado un control WebView MAUI de .NET 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. 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:

  1. Abre Safari en tu Mac.
  2. En Safari, selecciona la casilla Safari>Preferencias>Avanzado>Mostrar el menú Desarrollo en la barra de menús.
  3. Ejecuta tu aplicación Mac Catalyst.de .NET MAUI.
  4. En Safari, selecciona el menú Desarrollar > {Nombre del dispositivo}, donde el marcador de posición {Device name} es el nombre del dispositivo, como Macbook 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.