Hospedaje e implementación de ASP.NET Core Blazor WebAssembly

Nota

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

En este artículo se explica cómo hospedar e implementar Blazor WebAssembly con ASP.NET Core, redes de entrega de contenido (CDN), servidores de archivos y GitHub Pages.

Precaución

En este artículo se hace referencia a CentOS, una distribución de Linux que está cerca del estado Fin de vida (EOL). Tenga en cuenta su uso y planifique en consecuencia. Para más información, consulte la sección CentOS de este artículo.

Con el modelo de hospedaje de Blazor WebAssembly:

  • La aplicación Blazor, sus dependencias y el entorno de ejecución de .NET se descargan en el explorador en paralelo.
  • La aplicación se ejecuta directamente en el subproceso de interfaz de usuario del explorador.

Este artículo pertenece al escenario de implementación donde la aplicación Blazor se coloca en un servidor o servicio web de hospedaje estático; .NET no se usa para suministrar la aplicación Blazor. Esta estrategia se trata en la sección Implementación independiente, que incluye información sobre cómo hospedar una aplicación Blazor WebAssembly como una subaplicación de IIS.

Se admiten las estrategias de implementación siguientes:

Reducir el tamaño máximo del montón para algunos exploradores de dispositivo móvil

Al compilar una aplicación Blazor que se ejecuta en el cliente (proyecto .Client de una aplicación web de Blazor o una aplicación de Blazor WebAssembly independiente) y tiene como destino exploradores de dispositivos móviles, especialmente Safari en iOS, la disminución de la memoria máxima de la aplicación con la propiedad MSBuild EmccMaximumHeapSize puede ser necesaria. El valor predeterminado es 2 147 483 648 bytes, que puede ser demasiado grande y provocar el bloqueo de la aplicación si intenta asignar más memoria y el navegador no se la concede. En el ejemplo siguiente se establece el valor en 268 435 456 bytes en el archivo Program:

Al compilar una aplicación Blazor WebAssembly que tenga como destino exploradores de dispositivos móviles, especialmente Safari en iOS, es posible que sea necesario reducir la memoria máxima de la aplicación con la propiedad MSBuild EmccMaximumHeapSize. El valor predeterminado es 2 147 483 648 bytes, que puede ser demasiado grande y provocar el bloqueo de la aplicación si intenta asignar más memoria y el navegador no se la concede. En el ejemplo siguiente se establece el valor en 268 435 456 bytes en el archivo Program:

<EmccMaximumHeapSize>268435456</EmccMaximumHeapSize>

Para obtener más información sobre las propiedades y destinos de MSBuild de Mono/WebAssembly, consulte WasmApp.Common.targets (repositorio de GitHub dotnet/runtime).

Formato de empaquetado de Webcil para ensamblados .NET

Webcil es un formato de empaquetado compatible con la web para ensamblados .NET diseñados para permitir el uso de Blazor WebAssembly en entornos de red restrictivos. Los archivos Webcil usan un contenedor WebAssembly estándar, donde los ensamblados se implementan como archivos WebAssembly que usan la extensión de archivo estándar .wasm.

Webcil es el formato de empaquetado predeterminado al publicar una aplicación Blazor WebAssembly. Para deshabilitar el uso de Webcil, establezca la siguiente propiedad MS Build en el archivo de proyecto de la aplicación:

<PropertyGroup>
  <WasmEnableWebcil>false</WasmEnableWebcil>
</PropertyGroup>

Personalización de la carga de los recursos de arranque

Personalice la forma en que se cargan los recursos de arranque mediante la API loadBootResource. Para obtener más información, vea Inicio de Blazor de ASP.NET Core.

Compresión

Cuando se publica una aplicación Blazor WebAssembly, la salida se comprime estáticamente durante la publicación para reducir el tamaño de la aplicación y acabar con la necesidad de compresión en tiempo de ejecución. Se usan los algoritmos de compresión siguientes:

Blazor se basa en el host para proporcionar los archivos comprimidos adecuados. Al hospedar una aplicación independiente Blazor WebAssembly, puede que sea necesario realizar trabajo adicional para garantizar que se proporcionan los archivos comprimidos estáticamente:

Blazor se basa en el host para proporcionar los archivos comprimidos adecuados. Cuando se usa un proyecto Blazor WebAssemblyhospedado de ASP.NET Core, el proyecto host tiene capacidad para realizar la negociación de contenido y proporcionar los archivos comprimidos estáticamente. Al hospedar una aplicación independiente Blazor WebAssembly, puede que sea necesario realizar trabajo adicional para garantizar que se proporcionan los archivos comprimidos estáticamente:

  • Para ver la configuración de compresión de web.config de IIS, vea la sección IIS: compresión Brotli y Gzip.
  • Al hospedar en soluciones de hospedaje estáticas que no admiten la negociación de contenido de archivos comprimidos estáticamente, considere la posibilidad de configurar la aplicación para capturar y descodificar archivos comprimidos Brotli:

Obtenga el descodificador Brotli de JavaScript del repositorio de GitHub google/brotli. El archivo del descodificador minificado se llama decode.min.js y se encuentra en la carpeta js del repositorio.

Nota

Si se produce un error en la versión minificada del script decode.js (decode.min.js), en su lugar, pruebe a usar la versión no minificada (decode.js).

Actualice la aplicación para que use el descodificador.

En el archivo wwwroot/index.html, establezca autostart en false en la etiqueta Blazor de <script>:

<script src="_framework/blazor.webassembly.js" autostart="false"></script>

Después de la etiqueta <script> de Blazor y antes de la etiqueta de cierre </body>, agregue el siguiente bloque <script> de código de JavaScript.

Aplicación web Blazor:

<script type="module">
  import { BrotliDecode } from './decode.min.js';
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration' && type !== 'manifest') {
          return (async function () {
            const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
            if (!response.ok) {
              throw new Error(response.statusText);
            }
            const originalResponseBuffer = await response.arrayBuffer();
            const originalResponseArray = new Int8Array(originalResponseBuffer);
            const decompressedResponseArray = BrotliDecode(originalResponseArray);
            const contentType = type === 
              'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
            return new Response(decompressedResponseArray, 
              { headers: { 'content-type': contentType } });
          })();
        }
      }
    }
  });
</script>

Blazor WebAssembly independiente:

<script type="module">
  import { BrotliDecode } from './decode.min.js';
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration') {
        return (async function () {
          const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
          if (!response.ok) {
            throw new Error(response.statusText);
          }
          const originalResponseBuffer = await response.arrayBuffer();
          const originalResponseArray = new Int8Array(originalResponseBuffer);
          const decompressedResponseArray = BrotliDecode(originalResponseArray);
          const contentType = type === 
            'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
          return new Response(decompressedResponseArray, 
            { headers: { 'content-type': contentType } });
        })();
      }
    }
  });
</script>

Para obtener más información sobre la carga de los recursos de arranque, vea Inicio de Blazor de ASP.NET Core.

Para deshabilitar la compresión, agregue la propiedad CompressionEnabled de MSBuild al archivo del proyecto de la aplicación y establezca el valor en false:

<PropertyGroup>
  <CompressionEnabled>false</CompressionEnabled>
</PropertyGroup>

La propiedad CompressionEnabled se puede pasar al comando dotnet publish con la sintaxis siguiente en un shell de comandos:

dotnet publish -p:CompressionEnabled=false

Para deshabilitar la compresión, agregue la propiedad BlazorEnableCompression de MSBuild al archivo del proyecto de la aplicación y establezca el valor en false:

<PropertyGroup>
  <BlazorEnableCompression>false</BlazorEnableCompression>
</PropertyGroup>

La propiedad BlazorEnableCompression se puede pasar al comando dotnet publish con la sintaxis siguiente en un shell de comandos:

dotnet publish -p:BlazorEnableCompression=false

Reescritura de las URL para conseguir un enrutamiento correcto

Enrutar las solicitudes de los componentes de página de una aplicación Blazor WebAssembly no es tan sencillo como enrutar las solicitudes de una aplicación Blazor Server. Imagine que tiene una aplicación Blazor WebAssembly con dos componentes:

  • Main.razor: se carga en la raíz de la aplicación y contiene un vínculo al componente About (href="About").
  • About.razor: componente About.

Cuando se solicita el documento predeterminado de la aplicación mediante la barra de direcciones del explorador (por ejemplo, https://www.contoso.com/):

  1. El explorador realiza una solicitud.
  2. Se devuelve la página predeterminada, que suele ser index.html.
  3. index.html arranca la aplicación.
  4. Router carga el componente y se representa el componente RazorMain.

En la página principal, la selección del vínculo al componente About funciona en el cliente porque el enrutador de Blazor impide que el explorador haga una solicitud en Internet a www.contoso.com sobre About y presenta el propio componente About representado. Todas las solicitudes de puntos de conexión internos dentro de la aplicación Blazor WebAssembly funcionan del mismo modo: Las solicitudes no desencadenan solicitudes basadas en el explorador a recursos hospedados en el servidor en Internet. El enrutador controla las solicitudes de forma interna.

Si se realiza una solicitud mediante la barra de direcciones del explorador para www.contoso.com/About, se produce un error. Este recurso no existe en el host de Internet de la aplicación, por lo que se devuelve una respuesta 404 No encontrado.

Dado que los exploradores solicitan páginas del lado cliente a hosts basados en Internet, los servidores web y los servicios de hospedaje deben reescribir todas las solicitudes de recursos que no estén físicamente en el servidor a la página index.html. Cuando se devuelve index.html, el enrutador Blazor de la aplicación se hace cargo y responde con el recurso correcto.

Al implementar en un servidor IIS, puede usar el módulo URL Rewrite con el archivo web.config publicado de la aplicación. Para más información, consulte la sección sobre IIS.

Implementación hospedada con ASP.NET Core

Una implementación hospedada se encarga de suministrar la aplicación Blazor WebAssembly a los exploradores desde una aplicación ASP.NET Core que se ejecuta en un servidor web.

La aplicación cliente de Blazor WebAssembly se publica en la carpeta /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot de la aplicación de servidor, junto con cualquier otro recurso web estático de la aplicación de servidor. Las dos aplicaciones se implementan juntas. Se requiere un servidor web que pueda hospedar una aplicación ASP.NET Core. En el caso de una implementación hospedada, Visual Studio incluye la plantilla de proyecto Aplicación de Blazor WebAssembly (plantilla blazorwasm si se usa el comando dotnet new) con la opción Hosted seleccionada (-ho|--hosted si se usa el comando dotnet new).

Para más información, consulte los siguientes artículos.

Implementación hospedada de un archivo ejecutable dependiente de la plataforma para una plataforma específica

Para implementar una aplicación Blazor WebAssembly hospedada como un ejecutable dependiente del marco para una plataforma específica (no independiente), siga estas instrucciones basadas en las herramientas que se usan.

Visual Studio

De forma predeterminada, se configura una implementación independiente para un perfil de publicación generado (.pubxml). Compruebe que el perfil de publicación del proyecto Server contiene la <SelfContained> propiedad MSBuild establecida en false.

En el archivo de perfil de publicación .pubxml de la carpeta Properties del proyecto Server:

<SelfContained>false</SelfContained>

Establezca el identificador de tiempo de ejecución (RID) mediante el valor de Tiempo de ejecución de destino en el área Configuración de la interfaz de usuario de Publicación, que genera la propiedad MSBuild <RuntimeIdentifier> en el perfil de publicación:

<RuntimeIdentifier>{RID}</RuntimeIdentifier>

en la configuración anterior, el marcador de posición {RID} es el identificador de tiempo de ejecución (RID).

Publique el proyecto Server en la configuración de Versión.

Nota

Es posible publicar una aplicación con la configuración del perfil de publicación mediante la CLI de .NET pasando /p:PublishProfile={PROFILE} al comando dotnet publish, donde el marcador de posición {PROFILE} es el perfil. Para obtener más información, consulte las secciones Publicar los perfiles y Ejemplo de publicación de carpetas en el artículo Perfiles de publicación (.pubxml) de Visual Studio para la implementación de aplicaciones ASP.NET Core. Si pasa el RID en el comando dotnet publish y no en el perfil de publicación, use la propiedad MSBuild (/p:RuntimeIdentifier) con el comando, no con la opción -r|--runtime.

CLI de .NET

Configure una implementación independiente colocando la propiedad MSBuild <SelfContained> en un <PropertyGroup> en el archivo de proyecto del proyecto Server establecido en false:

<SelfContained>false</SelfContained>

Importante

La propiedad SelfContained debe colocarse en el archivo de proyecto del proyecto Server. La propiedad no se puede establecer correctamente con el comando dotnet publish mediante la opción --no-self-contained o la propiedad MSBuild /p:SelfContained=false.

Establezca el identificador en tiempo de ejecución (RID) mediante cualquiera de los métodos siguientes:

  • Opción 1: Establezca el RID en un <PropertyGroup> en el archivo de proyecto del proyecto Server:

    <RuntimeIdentifier>{RID}</RuntimeIdentifier>
    

    en la configuración anterior, el marcador de posición {RID} es el identificador de tiempo de ejecución (RID).

    Publique la aplicación en la configuración de versión del proyecto Server:

    dotnet publish -c Release
    
  • Opción 2: Pase el RID en el comando dotnet publish como la propiedad de MSBuild (/p:RuntimeIdentifier), no con la opción -r|--runtime:

    dotnet publish -c Release /p:RuntimeIdentifier={RID}
    

    En el comando anterior, el marcador de posición {RID} es el identificador de tiempo de ejecución (RID).

Para más información, consulte los siguientes artículos.

Implementación hospedada con varias aplicaciones Blazor WebAssembly

Para más información, consulte Varias aplicaciones de ASP.NET Core Blazor WebAssembly hospedadas.

Implementación independiente

Una implementación independiente suministra la aplicación Blazor WebAssembly como un conjunto de archivos estáticos que los clientes solicitan directamente. Cualquier servidor de archivos estático es capaz de suministrar la aplicación Blazor.

Los recursos de implementación independientes se publican en la carpeta /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot.

Azure App Service

Las aplicaciones Blazor WebAssembly se pueden implementar en Azure App Services en Windows, que hospeda la aplicación en IIS.

Actualmente no se admite la implementación de una aplicación Blazor WebAssembly independiente en Azure App Service para Linux. Se recomienda hospedar una aplicación independiente Blazor WebAssembly mediante Azure Static Web Apps, que admite este escenario.

Azure Static Web Apps

Implemente una aplicación Blazor WebAssembly en Azure Static Web Apps mediante cualquiera de los enfoques siguientes:

Implementación desde Visual Studio

Para realizar la implementación desde Visual Studio, cree un perfil de publicación para Azure Static Web Apps:

  1. Guarde cualquier trabajo no guardado en el proyecto, ya que es posible que se requiera un reinicio de Visual Studio durante el proceso.

  2. En la interfaz de usuario de publicación de Visual Studio, seleccione Destino>Azure>Destino específico>Azure Static Web Apps para crear un perfil de publicación.

  3. Si el componente Azure WebJobs Tools para Visual Studio no está instalado, aparece un mensaje para instalar el componente ASP.NET y desarrollo web. Siga las indicaciones para instalar las herramientas mediante el Instalador de Visual Studio. Visual Studio se cierra y vuelve a abrirse automáticamente al instalar las herramientas. Una vez instaladas las herramientas, comience en el primer paso para crear el perfil de publicación.

  4. En la configuración del perfil de publicación, proporcione el nombre de la suscripción. Seleccione una instancia existente o seleccione Crear una nueva instancia. Al crear una nueva instancia en la interfaz de usuario Crear aplicación web estática de Azure Portal, establezca Detalles de la implementación>Origen en Otro. Espere a que la implementación se complete en Azure Portal antes de continuar.

  5. En la configuración del perfil de publicación, seleccione la instancia de Azure Static Web Apps del grupo de recursos de la instancia. Seleccione Finalizar para crear el perfil de publicación. Si Visual Studio solicita que instale la CLI de Static Web Apps (SWA), instale la CLI siguiendo las indicaciones. La CLI de SWA requiere NPM/Node.js (documentación de Visual Studio).

Una vez creado el perfil de publicación, implemente la aplicación en la instancia de Azure Static Web Apps mediante el perfil de publicación seleccionando el botón Publicar.

Implementación desde GitHub

Para realizar la implementación desde un repositorio de GitHub, consulte Tutorial: Creación de una aplicación web estática con Blazor en Azure Static Web Apps.

IIS

IIS es un servidor de archivos estáticos compatible con las aplicaciones Blazor. Para configurar IIS para hospedar Blazor, consulte Compilación de un sitio web estático en IIS.

Los recursos publicados se crean en la carpeta /bin/Release/{TARGET FRAMEWORK}/publish o bin\Release\{TARGET FRAMEWORK}\browser-wasm\publish, en función de la versión del SDK que se use y de donde el marcador de posición {TARGET FRAMEWORK} sea la plataforma de destino. Hospede el contenido de la carpeta publish en el servidor web o el servicio de hospedaje.

web.config

Cuando se publica un proyecto de Blazor, se crea un archivo web.config con la siguiente configuración de IIS:

  • tipos MIME
  • Se habilita la compresión HTTP de los siguientes tipos MIME:
    • application/octet-stream
    • application/wasm
  • Se establecen reglas del módulo URL Rewrite:
    • Proporcione el subdirectorio donde residen los recursos estáticos de la aplicación (wwwroot/{PATH REQUESTED}).
    • Cree el enrutamiento de reserva de SPA para que las solicitudes de recursos que no sean archivos se redirijan al documento predeterminado de la aplicación en su carpeta de recursos estáticos (wwwroot/index.html).

Uso de una web.config personalizada

Para usar un archivo web.config personalizado:

  1. Coloque el archivo web.config personalizado en la carpeta raíz del proyecto.
  2. Publique el proyecto. Para obtener más información, vea Hospedaje e implementación de Blazor en ASP.NET Core.
  1. Coloque el archivo web.config personalizado en la carpeta raíz del proyecto. En el caso de una Blazor WebAssemblysolución hospedada, coloque el archivo en la carpeta del proyecto de Server.
  2. Publique el proyecto. Para una solución de Blazor WebAssembly hospedada, publique la solución desde el proyecto Server. Para más información, vea Hospedaje e implementación de ASP.NET Core Blazor.

Si la generación o transformación web.config del SDK durante la publicación no mueve el archivo a recursos publicados en la carpeta publish o modifica la configuración personalizada en el archivo personalizado web.config, use cualquiera de los enfoques siguientes según sea necesario para tomar el control total del proceso:

  • Si el SDK no genera el archivo, por ejemplo, en una aplicación independiente Blazor WebAssembly en /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot o bin\Release\{TARGET FRAMEWORK}\browser-wasm\publish, en función de la versión del SDK que se use y de donde el marcador de posición {TARGET FRAMEWORK} sea la plataforma de destino, establezca la propiedad <PublishIISAssets> en true en el archivo de proyecto (.csproj). Normalmente, para las aplicaciones WebAssembly independientes, esta es la única configuración necesaria para mover un archivo personalizado web.config y evitar la transformación del archivo por parte del SDK.

    <PropertyGroup>
      <PublishIISAssets>true</PublishIISAssets>
    </PropertyGroup>
    
  • Deshabilite la transformación web.config del SDK en el archivo de proyecto (.csproj):

    <PropertyGroup>
      <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    </PropertyGroup>
    
  • Agregue un destino personalizado al archivo de proyecto (.csproj) para mover un archivo personalizado web.config. En el ejemplo siguiente, el desarrollador coloca el archivo personalizado web.config en la raíz del proyecto. Si el archivo web.config reside en otro lugar, especifique la ruta de acceso al archivo en SourceFiles. En el ejemplo siguiente se especifica la carpeta publish con $(PublishDir), pero se proporciona una ruta de acceso a DestinationFolder para una ubicación de salida personalizada.

    <Target Name="CopyWebConfig" AfterTargets="Publish">
      <Copy SourceFiles="web.config" DestinationFolder="$(PublishDir)" />
    </Target>
    

Instalación del módulo URL Rewrite

El módulo URL Rewrite es necesario para reescribir las URL. El módulo no se instala de forma predeterminada y no está disponible para instalar como una característica de servicio de rol del servidor web (IIS). El módulo se debe descargar desde el sitio web de IIS. Use el instalador de plataforma web para instalar el módulo:

  1. De forma local, vaya a la página de descargas del módulo URL Rewrite. En el caso de la versión en inglés, seleccione WebPI para descargar el instalador de WebPI. En el caso de otros idiomas, seleccione la arquitectura adecuada del servidor (x86/x64) para descargar el instalador.
  2. Copie el instalador en el servidor. Ejecute el instalador. Haga clic en el botón Instalar y acepte los términos de licencia. No es necesario reiniciar el servidor al finalizar la instalación.

Configuración del sitio web

Configure la ruta de acceso física del sitio web a la carpeta de la aplicación. La carpeta contiene:

  • El archivo web.config que usa IIS para configurar el sitio web, incluidas las reglas de redireccionamiento y los tipos de contenido de archivo necesarios.
  • La carpeta de recursos estáticos de la aplicación.

Hospedaje como subaplicación de IIS

Si una aplicación independiente se hospeda como una subaplicación de IIS, realice una de las siguientes acciones:

  • Deshabilite el controlador del módulo de ASP.NET Core heredado.

    Para quitar el controlador del archivo web.config publicado de la aplicación Blazor, agregue una sección <handlers> a la sección <system.webServer> del archivo:

    <handlers>
      <remove name="aspNetCore" />
    </handlers>
    
  • Deshabilite la herencia de la sección <system.webServer> de la aplicación raíz (principal) mediante un elemento <location> con inheritInChildApplications establecido en false:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <location path="." inheritInChildApplications="false">
        <system.webServer>
          <handlers>
            <add name="aspNetCore" ... />
          </handlers>
          <aspNetCore ... />
        </system.webServer>
      </location>
    </configuration>
    

    Nota

    Deshabilitar la herencia de la sección <system.webServer> de la aplicación raíz (primaria) es la configuración predeterminada para las aplicaciones publicadas mediante el SDK de .NET.

Además de configurarse la ruta de acceso base de la aplicación, se quita el controlador o se deshabilita la herencia. En el archivo index.html de la aplicación, establezca la ruta de acceso base de la aplicación en el alias de IIS que ha usado al configurar la subaplicación en IIS.

Configure la ruta de acceso base de la aplicación siguiendo las indicaciones del artículo Hospedar e implementar ASP.NET Core Blazor.

Compresión Brotli y Gzip

Esta sección solo se aplica a aplicaciones Blazor WebAssembly independientes.

Esta sección solo se aplica a aplicaciones Blazor WebAssembly independientes. Las aplicaciones hospedadas de Blazor usan un archivo web.config de la aplicación ASP.NET Core predeterminado, no el archivo vinculado en esta sección.

IIS se puede configurar a través de web.config para dar servicio a recursos de Blazor comprimidos con Brotli o Gzip para aplicaciones de Blazor WebAssembly independientes. Para ver un archivo de configuración de ejemplo, consulte web.config.

Podría ser necesaria una configuración adicional del archivo web.config de ejemplo en los escenarios siguientes:

  • La especificación de la aplicación requiere cualquiera de las siguientes opciones:
    • Servir archivos comprimidos que no están configurados por el archivo web.config de ejemplo.
    • Servir archivos comprimidos configurados por el archivo web.config de ejemplo en un formato sin comprimir.
  • La configuración de IIS del servidor (por ejemplo, applicationHost.config) proporciona valores predeterminados de IIS de nivel de servidor. En función de la configuración de nivel de servidor, es posible que la aplicación requiera una configuración de IIS diferente de la que contiene el archivo de web.config de ejemplo.

Para más información sobre los archivos personalizados web.config, consulte la sección Uso de web.config personalizado.

Solución de problemas

Si se recibe un error 500 Error interno del servidor y el administrador de IIS produce errores al intentar acceder a la configuración del sitio web, confirme que el módulo URL Rewrite está instalado. Si no lo está, IIS no puede analizar el archivo web.config. Esto impide que el Administrador de IIS cargue la configuración del sitio web y que el sitio web suministre los archivos estáticos de Blazor.

Para obtener más información sobre la solución de problemas de implementaciones en IIS, consulte Solución de ASP.NET Core {1}en Azure App Service e IIS.

Azure Storage

El hospedaje de archivos estáticos de Azure Storage permite el hospedaje de aplicaciones Blazor sin servidor. Se admiten nombres de dominio personalizados, Azure Content Delivery Network (CDN) y HTTPS.

Cuando el servicio de blob está habilitado para el hospedaje de sitios web estáticos en una cuenta de almacenamiento:

  • Establece el nombre de documento de índice en index.html.
  • Establece la ruta de acceso del documento de error en index.html. Los componentes Razor y otros puntos de conexión que no son de archivo no residen en las rutas de acceso físicas del contenido estático almacenado por el servicio de blob. Cuando se recibe una solicitud de uno de estos recursos que debe controlar el enrutador de Blazor, el error 404 - No encontrado generado por el servicio de blob enruta la solicitud a la ruta de acceso del documento de error. Se devuelve el blob index.html, y el enrutador de Blazor carga y procesa la ruta de acceso.

Si los archivos no se cargan en tiempo de ejecución debido a tipos MIME inadecuados en los encabezados Content-Type de los archivos, haga algunas de las acciones siguientes:

  • Configure las herramientas para establecer los tipos MIME correctos (encabezados Content-Type) cuando se implementen los archivos.

  • Cambie los tipos MIME (encabezados Content-Type) de los archivos una vez que se implementa la aplicación.

    En cada archivo del Explorador de Storage (Azure Portal) haga lo siguiente:

    1. Haga clic con el botón derecho en el archivo y seleccione Propiedades.
    2. Establezca el valor de ContentType y seleccione el botón Guardar.

Para más información, consulte Hospedaje de sitios web estáticos en Azure Storage.

Nginx

El siguiente archivo nginx.conf se ha simplificado para mostrar cómo hay que configurar Nginx para enviar el archivo index.html siempre que no pueda encontrar un archivo correspondiente en el disco.

events { }
http {
    server {
        listen 80;

        location / {
            root      /usr/share/nginx/html;
            try_files $uri $uri/ /index.html =404;
        }
    }
}

Al establecer el límite de velocidad de ráfaga de NGINX con limit_req, las aplicaciones de Blazor WebAssembly pueden requerir un valor de parámetro burst grande para acomodar el número relativamente elevado de solicitudes realizadas por una aplicación. Inicialmente, establezca el valor en al menos 60:

http {
    server {
        ...

        location / {
            ...

            limit_req zone=one burst=60 nodelay;
        }
    }
}

Aumente el valor si las herramientas de desarrollo del explorador o la herramienta de tráfico de red indican que las solicitudes reciben un código de estado 503: Servicio no disponible.

Para obtener más información sobre la configuración del servidor web de producción de Nginx, consulte Creating NGINX Plus and NGINX Configuration Files (Creación de archivos de configuración de NGINX y NGINX Plus).

CentOS

El 30 de junio de 2024, CentOS alcanza el estado Final del ciclo de vida (EOL) y dejará de ser compatible con servidores web para hospedaje en Blazor WebAssembly. Para obtener más información, consulte los siguientes recursos:

Apache

Para implementar una aplicación Blazor WebAssembly en CentOS 7 o posterior:

  1. Cree el archivo de configuración de Apache. El siguiente ejemplo es un archivo de configuración simplificado (blazorapp.config):
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias *.example.com

    DocumentRoot "/var/www/blazorapp"
    ErrorDocument 404 /index.html

    AddType application/wasm .wasm

    <Directory "/var/www/blazorapp">
        Options -Indexes
        AllowOverride None
    </Directory>

    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
    </IfModule>

    ErrorLog /var/log/httpd/blazorapp-error.log
    CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias *.example.com

    DocumentRoot "/var/www/blazorapp"
    ErrorDocument 404 /index.html

    AddType application/wasm .wasm
    AddType application/octet-stream .dll

    <Directory "/var/www/blazorapp">
        Options -Indexes
        AllowOverride None
    </Directory>

    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
    </IfModule>

    ErrorLog /var/log/httpd/blazorapp-error.log
    CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>
  1. Coloque el archivo de configuración de Apache en el directorio /etc/httpd/conf.d/, que es el directorio de configuración de Apache predeterminado en CentOS 7.

  2. Coloque los archivos de la aplicación en el directorio /var/www/blazorapp (la ubicación especificada para DocumentRoot en el archivo de configuración).

  3. Reinicie el servicio de Apache.

Para obtener más información, vea mod_mime y mod_deflate.

GitHub Pages

La acción predeterminada de GitHub, que implementa páginas, omite la implementación de carpetas que empiezan por un carácter de subrayado como, por ejemplo, la carpeta_framework. Para implementar carpetas que empiezan por el carácter de subrayado, añada un archivo vacío .nojekyll a la rama de Git.

Git trata los archivos de JavaScript (JS) como, por ejemplo, blazor.webassembly.js, como texto y convierte los finales de línea CRLF (retorno de carro-salto de línea) a LF (salto de línea) en la canalización de implementación. Estos cambios en los archivos JS generan hashes de archivo distintos de los que Blazor envía al cliente en el archivo blazor.boot.json. Las discordancias dan lugar a errores de comprobación de integridad en el cliente. Un enfoque para resolver este problema es añadir un archivo .gitattributes con la línea *.js binary antes de añadir los recursos de la aplicación a la rama de Git. La línea *.js binary configura Git para que trate los archivos JS como archivos binarios, lo que evita su procesamiento en la canalización de implementación. Los hashes de los archivos no procesados coincidirán con las entradas del archivo blazor.boot.json y las comprobaciones de integridad del lado cliente se pasarán. Para obtener más información, consulte ASP.NET Core Blazor WebAssembly Runtime de .NET y el almacenamiento en caché de lote de aplicaciones.

Para controlar las reescrituras de URL, agregue un archivo wwwroot/404.html con un script que controle el redireccionamiento de la solicitud a la página index.html. Para obtener un ejemplo, consulte el repositorio de GitHub SteveSandersonMS/BlazorOnGitHubPages:

Si usa un sitio de proyecto en lugar de un sitio de la organización, actualice la etiqueta <base> en wwwroot/index.html. Defina el valor del atributo href con el nombre del repositorio de GitHub con una barra diagonal final (por ejemplo, /my-repository/). En el repositorio de GitHub SteveSandersonMS/BlazorOnGitHubPages, el elemento href base se actualiza cuando el archivo de configuración .github/workflows/main.yml realiza la publicación.

Nota:

El repositorio de GitHub SteveSandersonMS/BlazorOnGitHubPages no es propiedad de .NET Foundation o Microsoft, ni tampoco se encargan de su mantenimiento ni es compatible con ellos.

Independiente con Docker

Una aplicación independiente Blazor WebAssembly se publica como un conjunto de archivos estáticos que hospeda un servidor de archivos estáticos.

Para hospedar la aplicación en Docker:

  • Elija un contenedor de Docker con compatibilidad con el servidor web, como Ngnix o Apache.
  • Copie los recursos de la carpeta publish en una carpeta de ubicación definida en el servidor web para atender archivos estáticos.
  • Aplique la configuración adicional según sea necesario para atender la aplicación Blazor WebAssembly.

Para ver documentación adicional, consulte los siguientes recursos:

Valores de configuración de host

Las aplicaciones Blazor WebAssembly pueden aceptar los siguientes valores de configuración de host como argumentos de línea de comandos en tiempo de ejecución en el entorno de desarrollo.

Raíz del contenido

El argumento --contentroot establece la ruta de acceso absoluta al directorio que incluye los archivos de contenido de la aplicación (raíz del contenido). En los ejemplos siguientes, /content-root-path es la ruta de acceso raíz del contenido de la aplicación.

  • Pase el argumento al ejecutar la aplicación de forma local en un símbolo del sistema. En el directorio de la aplicación, ejecute lo siguiente:

    dotnet run --contentroot=/content-root-path
    
  • Agregue una entrada al archivo launchSettings.json de la aplicación en el perfil IIS Express. Esta configuración se utiliza cuando se ejecuta la aplicación mediante el depurador de Visual Studio y desde un símbolo del sistema con dotnet run.

    "commandLineArgs": "--contentroot=/content-root-path"
    
  • En Visual Studio, especifique el argumento en Propiedades>Depuración>Argumentos de la aplicación. Al establecer el argumento en la página de propiedades de Visual Studio, se agrega el argumento al archivo launchSettings.json.

    --contentroot=/content-root-path
    

Ruta de acceso base

El argumento --pathbase establece la ruta de acceso base de la aplicación para una aplicación que se ejecuta localmente con una ruta de acceso de URL relativa que no es raíz (el valor href de la etiqueta <base> se establece en una ruta de acceso que no sea / para ensayo y producción). En los ejemplos siguientes, /relative-URL-path es la ruta de acceso base de la aplicación. Para obtener más información, vea Ruta de acceso base de la aplicación.

Importante

A diferencia de la ruta de acceso proporcionada al valor href de la etiqueta <base>, no incluya una barra diagonal final (/) al pasar el valor del argumento --pathbase. Si se proporciona la ruta de acceso base de la aplicación en la etiqueta <base> como <base href="/CoolApp/"> (se incluye una barra diagonal final), se pasa el valor del argumento de línea de comandos como --pathbase=/CoolApp (sin barra diagonal final).

  • Pase el argumento al ejecutar la aplicación de forma local en un símbolo del sistema. En el directorio de la aplicación, ejecute lo siguiente:

    dotnet run --pathbase=/relative-URL-path
    
  • Agregue una entrada al archivo launchSettings.json de la aplicación en el perfil IIS Express. Esta configuración se utiliza cuando se ejecuta la aplicación mediante el depurador de Visual Studio y desde un símbolo del sistema con dotnet run.

    "commandLineArgs": "--pathbase=/relative-URL-path"
    
  • En Visual Studio, especifique el argumento en Propiedades>Depuración>Argumentos de la aplicación. Al establecer el argumento en la página de propiedades de Visual Studio, se agrega el argumento al archivo launchSettings.json.

    --pathbase=/relative-URL-path
    

Direcciones URL

El argumento --urls establece las direcciones IP o las direcciones de host con los puertos y protocolos en los que escuchar las solicitudes.

  • Pase el argumento al ejecutar la aplicación de forma local en un símbolo del sistema. En el directorio de la aplicación, ejecute lo siguiente:

    dotnet run --urls=http://127.0.0.1:0
    
  • Agregue una entrada al archivo launchSettings.json de la aplicación en el perfil IIS Express. Esta configuración se utiliza cuando se ejecuta la aplicación mediante el depurador de Visual Studio y desde un símbolo del sistema con dotnet run.

    "commandLineArgs": "--urls=http://127.0.0.1:0"
    
  • En Visual Studio, especifique el argumento en Propiedades>Depuración>Argumentos de la aplicación. Al establecer el argumento en la página de propiedades de Visual Studio, se agrega el argumento al archivo launchSettings.json.

    --urls=http://127.0.0.1:0
    

Implementación hospedada en Linux (Nginx)

Configure la aplicación con ForwardedHeadersOptions para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto siguiendo las instrucciones de Configuración de ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Para más información sobre cómo establecer la ruta base de la aplicación, incluida la configuración de la ruta de la subaplicación, vea Hospedaje e implementación de ASP.NET Core Blazor.

Siga las instrucciones para obtener una aplicación SignalR de ASP.NET Core con los siguientes cambios:

  • Quite la configuración de almacenamiento en búfer de proxy (proxy_buffering off;) porque la configuración solo se aplica a los eventos enviados por el servidor (SSE), que no son relevantes para las interacciones cliente-servidor de la aplicación Blazor.

  • Cambie la ruta de acceso delocation de /hubroute (location /hubroute { ... }) a la ruta de acceso de la subaplicación /{PATH} (location /{PATH} { ... }), donde el marcador de posición {PATH} es la ruta de acceso de la subaplicación.

    En el ejemplo siguiente se configura el servidor para una aplicación que responde a las solicitudes en la ruta de acceso raíz /:

    http {
        server {
            ...
            location / {
                ...
            }
        }
    }
    

    En el ejemplo siguiente se configura la ruta de acceso de la aplicación de /blazor:

    http {
        server {
            ...
            location /blazor {
                ...
            }
        }
    }
    

Para obtener más información e instrucciones de configuración, vea los recursos siguientes:

Configurar el recortador

Blazor realiza el recorte de lenguaje intermedio (IL) en cada compilación de lanzamiento para quitar el IL innecesario de los ensamblados de salida. Para más información, vea Configuración del recortador de ASP.NET Core Blazor.

Configurar el enlazador

Blazor realiza la vinculación de lenguaje intermedio (IL) en cada compilación de lanzamiento para quitar el IL innecesario de los ensamblados de salida. Para más información, vea Configuración del enlazador de ASP.NET Core Blazor.

Cambio de la extensión de nombre de archivo de los archivos DLL

Esta sección se aplica a ASP.NET Core 6.x y 7.x. En ASP.NET Core en .NET 8 o posterior, los ensamblados de .NET se implementan como archivos WebAssembly (.wasm) mediante el formato de archivo Webcil. En ASP.NET Core en .NET 8 o posterior, esta sección solo se aplica si el formato de archivo Webcil se ha deshabilitado en el archivo de proyecto de la aplicación.

Si un firewall, un programa antivirus o un dispositivo de seguridad de red bloquea la trasmisión de los archivos de la biblioteca de vínculos dinámicos (DLL) de la aplicación (.dll), puede seguir las instrucciones de esta sección para cambiar las extensiones de nombre de archivo de los archivos DLL publicados de la aplicación.

Nota

Cambiar las extensiones de nombre de archivo de los archivos DLL de la aplicación quizá no resuelva el problema porque muchos sistemas de seguridad examinan el contenido de los archivos de la aplicación, no solo comprueban las extensiones de archivo.

Si busca un enfoque más sólido en entornos que impiden la descarga y ejecución de archivos DLL, use ASP.NET Core en .NET 8 o posterior, que, de forma predeterminada, empaqueta ensamblados .NET como archivos WebAssembly (.wasm) mediante el formato de archivo Webcil. Para obtener más información, consulte la sección Formato de empaquetado de Webcil para ensamblados de .NET en una versión 8.0 o posterior de este artículo.

Existen enfoques de terceros para tratar este problema. Para obtener más información, consulte los recursos en Awesome Blazor.

Nota:

Cambiar las extensiones de nombre de archivo de los archivos DLL de la aplicación quizá no resuelva el problema porque muchos sistemas de seguridad examinan el contenido de los archivos de la aplicación, no solo comprueban las extensiones de archivo.

Para obtener un enfoque más sólido en entornos que bloquean la descarga y ejecución de archivos DLL, tome cualquiera de los enfoques siguientes:

  • Use ASP.NET Core en .NET 8 o posterior, que de forma predeterminada empaqueta ensamblados .NET como archivos WebAssembly (.wasm) con el formato de archivo Webcil. Para obtener más información, consulte la sección Formato de empaquetado de Webcil para ensamblados de .NET en una versión 8.0 o posterior de este artículo.
  • En ASP.NET Core en .NET 6 o posterior, use un diseño de implementación personalizado.

Existen enfoques de terceros para tratar este problema. Para obtener más información, consulte los recursos en Awesome Blazor.

Después de publicar la aplicación, use un script de shell o una canalización de compilación de DevOps para cambiar el nombre de los archivos .dll a fin de usar otra extensión de archivo en el directorio de la salida publicada de la aplicación.

En los siguientes ejemplos:

  • PowerShell (PS) se usa para actualizar las extensiones de archivo.
  • Los archivos .dll cambian de nombre para usar la extensión de archivo .bin de la línea de comandos.
  • Los archivos enumerados en el archivo blazor.boot.json publicado con una extensión de archivo .dll se actualizan a la extensión de archivo .bin.
  • Si los recursos de trabajo de servicio también están en uso, un comando de PowerShell actualiza los archivos .dll enumerados en el archivo service-worker-assets.js a la extensión de archivo .bin.

Para usar una extensión de archivo distinta de .bin, reemplace .bin en los siguientes comandos por la extensión de archivo deseada.

En Windows:

dir {PATH} | rename-item -NewName { $_.name -replace ".dll\b",".bin" }
((Get-Content {PATH}\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\blazor.boot.json

En el comando anterior, el marcador de posición {PATH} es la ruta de acceso a la carpeta _framework publicada (por ejemplo, .\bin\Release\net6.0\browser-wasm\publish\wwwroot\_framework desde la carpeta raíz del proyecto).

Si los recursos de trabajo de servicio también están en uso, haga lo siguiente:

((Get-Content {PATH}\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\service-worker-assets.js

En el comando anterior, el marcador de posición {PATH} es la ruta de acceso al archivo service-worker-assets.js publicado.

En Linux o macOS:

for f in {PATH}/*; do mv "$f" "`echo $f | sed -e 's/\.dll/.bin/g'`"; done
sed -i 's/\.dll"/.bin"/g' {PATH}/blazor.boot.json

En el comando anterior, el marcador de posición {PATH} es la ruta de acceso a la carpeta _framework publicada (por ejemplo, .\bin\Release\net6.0\browser-wasm\publish\wwwroot\_framework desde la carpeta raíz del proyecto).

Si los recursos de trabajo de servicio también están en uso, haga lo siguiente:

sed -i 's/\.dll"/.bin"/g' {PATH}/service-worker-assets.js

En el comando anterior, el marcador de posición {PATH} es la ruta de acceso al archivo service-worker-assets.js publicado.

Para dirigirse a los archivos comprimidos blazor.boot.json.gz y blazor.boot.json.br, adopte uno de los métodos siguientes:

  • Quite los archivos comprimidos blazor.boot.json.gz y blazor.boot.json.br. Con este enfoque, la compresión está deshabilitada.
  • Vuelva a comprimir el archivo blazor.boot.json actualizado.

La guía anterior del archivo blazor.boot.json comprimido también se aplica cuando se usan recursos de trabajo de servicio. Quite o vuelva a comprimir service-worker-assets.js.br y service-worker-assets.js.gz. De lo contrario, las comprobaciones de integridad de los archivos producirán errores en el explorador.

En el siguiente ejemplo de Windows para .NET 6 se usa un script de PowerShell colocado en la raíz del proyecto. El siguiente script, que deshabilita la compresión, es la base para una modificación adicional si quiere volver a comprimir el archivo blazor.boot.json.

ChangeDLLExtensions.ps1::

param([string]$filepath,[string]$tfm)
dir $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework | rename-item -NewName { $_.name -replace ".dll\b",".bin" }
((Get-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json.gz
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json.br

Si los recursos de trabajo de servicio también están en uso, agregue los siguientes comandos:

((Get-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js.gz
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js.br

En el archivo del proyecto, el script se ejecuta después de publicar la aplicación con la configuración de Release:

<Target Name="ChangeDLLFileExtensions" AfterTargets="AfterPublish" Condition="'$(Configuration)'=='Release'">
  <Exec Command="powershell.exe -command &quot;&amp; { .\ChangeDLLExtensions.ps1 '$(SolutionDir)' '$(TargetFramework)'}&quot;" />
</Target>

Nota

Al cambiar el nombre y realizar la carga diferida de los mismos ensamblados, vea las instrucciones de Ensamblados de carga diferida en Blazor WebAssembly de ASP.NET Core.

Normalmente, el servidor de la aplicación requiere la configuración de recursos estáticos para servir los archivos con la extensión actualizada. Para una aplicación hospedada por IIS, agregue una entrada de asignación MIME (<mimeMap>) para la nueva extensión de archivo en la sección de contenido estático (<staticContent>) de un archivo web.config personalizado. En el ejemplo siguiente se supone que la extensión de archivo se cambia de .dll a .bin:

<staticContent>
  ...
  <mimeMap fileExtension=".bin" mimeType="application/octet-stream" />
  ...
</staticContent>

Incluya una actualización para los archivos comprimidos si se usa compresión:

<mimeMap fileExtension=".bin.br" mimeType="application/octet-stream" />
<mimeMap fileExtension=".bin.gz" mimeType="application/octet-stream" />

Quite la entrada de la extensión de archivo .dll:

- <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />

Quite las entradas de los archivos .dll comprimidos si se usa compresión:

- <mimeMap fileExtension=".dll.br" mimeType="application/octet-stream" />
- <mimeMap fileExtension=".dll.gz" mimeType="application/octet-stream" />

Para más información sobre los archivos personalizados web.config, consulte la sección Uso de web.config personalizado.

Daños en la implementación anterior

Normalmente, en la implementación:

  • Solo se reemplazan los archivos que han cambiado, lo que normalmente da lugar a una implementación más rápida.
  • Los archivos existentes que no forman parte de la nueva implementación no se modifican para que los use la nueva implementación.

En raras ocasiones, los archivos persistentes de una implementación anterior pueden dañar una nueva implementación. La eliminación completa de la implementación existente (o la aplicación publicada localmente antes de la implementación) puede resolver el problema con una implementación dañada. A menudo, la eliminación de la implementación existente una vez es suficiente para resolver el problema, incluidos los DevOps compilación e implementación de la canalización.

Si determina que siempre es necesario borrar una implementación anterior cuando se está utilizando una canalización de compilación e implementación de DevOps, puede agregar temporalmente un paso a la canalización de compilación para eliminar la implementación anterior de cada nueva implementación hasta que solucione la causa exacta de los daños.

Resolución de errores de comprobación de integridad

Cuando Blazor WebAssembly descarga los archivos de inicio de una aplicación, le indica al navegador que realice comprobaciones de integridad en las respuestas. Blazor envía valores hash SHA-256 para DLL (.dll), WebAssembly (.wasm) y otros archivos del archivo blazor.boot.json, que no se almacenan en caché en los clientes. Los códigos hash de los archivos almacenados en caché se comparan con los del archivo blazor.boot.json. Para los archivos almacenados en caché con un hash correspondiente, Blazor usa los archivos almacenados en caché. De lo contrario, los archivos se solicitan desde el servidor. Después de descargar un archivo, su hash se comprueba de nuevo para la validación de integridad. El explorador genera un error si se produce un error en la comprobación de integridad de cualquier archivo descargado.

Algoritmo de Blazor para administrar la integridad de los archivos:

  • Garantiza que la aplicación no corre el riesgo de cargar un conjunto de archivos incoherentes, por ejemplo, si se aplica una nueva implementación al servidor web mientras el usuario se encuentra en el proceso de descarga de los archivos de aplicación. Los archivos incoherentes pueden dar lugar a un funcionamiento incorrecto de la aplicación.
  • Garantiza que el explorador del usuario nunca almacene en caché respuestas incoherentes o no válidas, lo que puede impedir que se inicie la aplicación aunque el usuario actualice manualmente la página.
  • Hace que sea seguro almacenar en caché las respuestas y no comprobar los cambios en el lado servidor hasta que cambien los códigos hash SHA-256 esperados, por lo que las cargas de páginas posteriores implican menos solicitudes y se completan mucho más rápido.

Si el servidor web devuelve respuestas que no coinciden con los códigos hash SHA-256 esperados, verá un error similar al del ejemplo siguiente en la consola para desarrolladores del explorador:

No se ha podido encontrar ninguna síntesis válida en el atributo "integrity" del recurso "https://myapp.example.com/_framework/MyBlazorApp.dll" con la integridad de SHA-256 calculada "IIa70iwvmEg5WiDV17OpQ5eCztNYqL186J56852RpJY=". El recurso se ha bloqueado.

En la mayoría de los casos, la advertencia no indica un problema con la comprobación de integridad. En su lugar, la advertencia normalmente significa que existe otro problema.

Para obtener el origen de referencia de arranque de Blazor WebAssembly, vea el archivo Boot.WebAssembly.ts en el repositorio dotnet/aspnetcore de GitHub.

Nota

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, use la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, vea Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Diagnóstico de problemas de integridad

Cuando se compila una aplicación, el manifiesto de blazor.boot.json generado describe los códigos hash SHA-256 de los recursos de arranque en el momento en que se ha generado la salida de la compilación. La comprobación de integridad se supera siempre que los algoritmos hash SHA-256 de blazor.boot.json coincidan con los archivos entregados al explorador.

Los motivos comunes por los que se produce un error incluyen:

  • La respuesta del servidor web es un error (por ejemplo, 404 No encontrado o 500 Error interno del servidor) en lugar del archivo solicitado por el explorador. El explorador lo detecta como un error de comprobación de integridad y no como un error de respuesta.
  • Algo ha cambiado el contenido de los archivos entre la compilación y la entrega de los archivos al explorador. Esto puede ocurrir:
    • Si el usuario o las herramientas de compilación modifican manualmente la salida de compilación.
    • Si algún aspecto del proceso de implementación ha modificado los archivos. Por ejemplo, si usa un mecanismo de implementación basado en Git, tenga en cuenta que Git convierte de forma transparente los finales de línea de estilo Windows en finales de línea de estilo Unix si confirma archivos en Windows y los comprueba en Linux. El cambio de los finales de línea de archivo cambia los algoritmos hash SHA-256. Para evitar este problema, considere la posibilidad de usar .gitattributes para tratar los artefactos de compilación como archivos binary.
    • El servidor web modifica el contenido del archivo como parte del servicio. Por ejemplo, algunas redes de distribución de contenido (CDN) intentan automáticamente minimizar HTML, con lo que se modifica. Es posible que tenga que deshabilitar estas características.
  • El archivo blazor.boot.json no se carga correctamente o se almacena en caché incorrectamente en el cliente. Entre las causas comunes se incluye una de las siguientes:
    • Código de desarrollador personalizado mal configurado o que no funciona correctamente.
    • Una o varias capas de almacenamiento en caché intermedias mal configuradas.

Para diagnosticar cuál de ellas se aplica en su caso:

  1. Lea el mensaje de error para darse cuenta de qué archivo está desencadenando el error.
  2. Abra las herramientas de desarrollo del explorador y mire en la pestaña Red. Si es necesario, vuelva a cargar la página para ver la lista de solicitudes y respuestas. Busque el archivo que desencadena el error en esa lista.
  3. Compruebe el código de estado HTTP en la respuesta. Si el servidor devuelve un valor distinto de 200 - Correcto (u otro código de estado 2XX), tiene un problema de servidor por diagnosticar. Por ejemplo, el código de estado 403 significa que hay un problema de autorización, mientras que el código de estado 500 significa que el servidor está dando error de una manera no especificada. Consulte los registros del servidor para diagnosticar y corregir la aplicación.
  4. Si el código de estado es 200 - Correcto para el recurso, examine el contenido de la respuesta en las herramientas de desarrollo del explorador y compruebe que el contenido coincida con los datos esperados. Por ejemplo, un problema común es configurar erróneamente el enrutamiento de modo que las solicitudes devuelvan los datos de index.html incluso para otros archivos. Asegúrese de que las respuestas a las solicitudes de .wasm son archivos binarios de WebAssembly y que las respuestas a las solicitudes de .dll son archivos binarios de ensamblado de .NET. Si no es así, tiene un problema de enrutamiento del lado servidor por diagnosticar.
  5. Trate de validar la salida publicada e implementada de la aplicación con el script de PowerShell para solucionar problemas de integridad.

Si confirma que el servidor está devolviendo datos plausiblemente correctos, debe haber algo más que modifique el contenido entre la compilación y la entrega del archivo. Para investigarlo:

  • Examine la cadena de herramientas de compilación y el mecanismo de implementación en caso de que estén modificando archivos después de compilarlos. Un ejemplo de esto es cuando GIT transforma los finales de línea de los archivos, tal y como se ha descrito anteriormente.
  • Examine el servidor web o la configuración de CDN en caso de que estén configurados para modificar las respuestas de forma dinámica (por ejemplo, intentando minimizar HTML). Está adecuado que el servidor web implemente la compresión HTTP (por ejemplo, devolviendo content-encoding: br o content-encoding: gzip), ya que esto no afecta al resultado después de la descompresión. Sin embargo, no es adecuado que el servidor web modifique los datos sin comprimir.

Script de PowerShell para solucionar problemas de integridad

Use el script integrity.ps1 de PowerShell para validar una aplicación Blazor publicada e implementada. El script se proporciona para PowerShell Core 7 o posterior como punto inicial cuando la aplicación tiene problemas de integridad que el marco Blazor no puede identificar. La personalización del script puede ser necesaria para las aplicaciones, incluso si se ejecuta en una versión de PowerShell posterior a la versión 7.2.0.

El script revisa los archivos de la carpeta publish y los descarga de la aplicación implementada para detectar problemas en los distintos manifiestos que contienen valores hash de integridad. Estas comprobaciones deben detectar los problemas más comunes:

  • Modificó un archivo en la salida publicada sin darse cuenta.
  • La aplicación no se implementó correctamente en el destino de la implementación o hubo algún cambio en el entorno del destino de la implementación.
  • Hay diferencias entre la aplicación implementada y la salida de la publicación de la aplicación.

Use el comando siguiente en un shell de comandos de PowerShell para invocar el script:

.\integrity.ps1 {BASE URL} {PUBLISH OUTPUT FOLDER}

En el ejemplo siguiente, el script se ejecuta en una aplicación que se ejecuta localmente en https://localhost:5001/:

.\integrity.ps1 https://localhost:5001/ C:\TestApps\BlazorSample\bin\Release\net6.0\publish\

Marcadores de posición:

  • {BASE URL}: la dirección URL de la aplicación implementada. Se requiere la barra diagonal (/).
  • {PUBLISH OUTPUT FOLDER}: la ruta de acceso a la carpeta publish de la aplicación o a la ubicación donde se publica la aplicación para la implementación.

Nota

Al clonar el repositorio de GitHub dotnet/AspNetCore.Docs, Bitdefender o cualquier otro antivirus del sistema podrían poner en cuarentena el script integrity.ps1. Normalmente, la tecnología de detección heurística de un antivirus intercepta el archivo, buscando simplemente patrones en archivos que podrían indicar la presencia de malware. Para evitar que el antivirus ponga el archivo en cuarentena, agregue una excepción al antivirus antes de clonar el repositorio. El ejemplo siguiente es una ruta de acceso típica al script en un sistema Windows. Ajuste la ruta de acceso según sea necesario para otros sistemas. El marcador de posición {USER} es el segmento de la ruta de acceso del usuario.

C:\Users\{USER}\Documents\GitHub\AspNetCore.Docs\aspnetcore\blazor\host-and-deploy\webassembly\_samples\integrity.ps1

Advertencia: La creación de excepciones para el antivirus es peligrosa y solo se debe realizar cuando tenga la certeza de que el archivo es seguro.

Comparar la suma de comprobación de un archivo con un valor de suma de comprobación válido no garantiza la seguridad de los archivos, pero modificar un archivo de forma que mantenga un valor de suma de comprobación no es trivial para los usuarios malintencionados. Por lo tanto, las sumas de comprobación son útiles como enfoque de seguridad general. Compare la suma de comprobación del archivo local integrity.ps1 con uno de los valores siguientes:

  • SHA256: 32c24cb667d79a701135cb72f6bae490d81703323f61b8af2c7e5e5dc0f0c2bb
  • MD5: 9cee7d7ec86ee809a329b5406fbf21a8

Obtenga la suma de comprobación del archivo en el sistema operativo Windows con el siguiente comando. Proporcione la ruta de acceso y el nombre de archivo para el marcador de posición {PATH AND FILE NAME} e indique el tipo de suma de comprobación que se debe generar para el marcador de posición {SHA512|MD5}, bien SHA256 o MD5:

CertUtil -hashfile {PATH AND FILE NAME} {SHA256|MD5}

Si tiene algún motivo para preocuparse de que la validación de la suma de comprobación no sea lo suficientemente segura en su entorno, consúltelo con el responsable de seguridad de su organización para obtener instrucciones.

Para obtener más información, consulte Información general sobre la protección contra amenazas del antivirus Microsoft Defender.

Deshabilitación de la comprobación de integridad para aplicaciones que no son de PWA

En la mayoría de los casos, no deshabilite la comprobación de integridad. Al deshabilitar la comprobación de integridad, no se soluciona el problema subyacente que ha causado las respuestas inesperadas y se pierden las ventajas mencionadas anteriormente.

Puede haber casos en los que no se pueda confiar en el servidor web para que devuelva respuestas coherentes, y solo le queda la opción de deshabilitar temporalmente las comprobaciones de integridad hasta que se resuelva el problema subyacente.

Para deshabilitar las comprobaciones de integridad, agregue lo siguiente a un grupo de propiedades en el archivo del proyecto de la aplicación Blazor WebAssembly (.csproj):

<BlazorCacheBootResources>false</BlazorCacheBootResources>

BlazorCacheBootResources también deshabilita el comportamiento predeterminado de Blazorde almacenar en caché .dll, .wasm y otros archivos según sus algoritmos hash SHA-256, ya que la propiedad indica que no se puede confiar en la exactitud de los algoritmos hash SHA-256. Incluso con esta configuración, es posible que la memoria caché HTTP normal del explorador siga almacenando en caché esos archivos, pero que esto suceda o no depende de la configuración del servidor web y de los encabezados de cache-control a los que sirve.

Nota

La propiedad BlazorCacheBootResources no deshabilita las comprobaciones de integridad de las aplicaciones web progresivas (PWA). Para obtener instrucciones relativas a las PWA, consulte la sección Deshabilitación de la comprobación de integridad para aplicaciones PWA.

No se puede proporcionar una lista exhaustiva de escenarios en los que es necesario deshabilitar la comprobación de integridad. Los servidores pueden responder a una solicitud de maneras arbitrarias fuera del ámbito del marco Blazor. El marco proporciona el valor BlazorCacheBootResources para que la aplicación se pueda ejecutar a costa de perder una garantía de integridad que la aplicación puede proporcionar. Una vez más, no se recomienda deshabilitar la comprobación de integridad, especialmente para las implementaciones de producción. Los desarrolladores deben intentar resolver el problema de integridad subyacente que provoca un error en la comprobación de la integridad.

Algunos casos generales que pueden causar problemas de integridad son los siguientes:

  • Se ejecuta en HTTP, donde no se puede comprobar la integridad.
  • Si el proceso de implementación modifica los archivos después de la publicación de alguna manera.
  • Si el host modifica los archivos de alguna manera.

Deshabilitación de la comprobación de integridad para aplicaciones PWA

La plantilla de aplicación web progresiva (PWA) de Blazor contiene un archivo service-worker.published.js sugerido que es responsable de capturar y almacenar archivos de la aplicación para su uso sin conexión. Se trata de un proceso independiente del mecanismo de inicio de la aplicación normal y tiene su propia lógica de comprobación de integridad independiente.

Dentro del archivo service-worker.published.js, está presente la línea siguiente:

.map(asset => new Request(asset.url, { integrity: asset.hash }));

Para deshabilitar la comprobación de la integridad, quite el parámetro integrity cambiando la línea por lo siguiente:

.map(asset => new Request(asset.url));

De nuevo, deshabilitar la comprobación de la integridad significa que se pierden las garantías de seguridad que ofrece este servicio. Por ejemplo, existe el riesgo de que si el explorador del usuario almacena en caché la aplicación en el momento exacto en que implementa una nueva versión, podría almacenar en caché algunos archivos de la implementación anterior y otros de la implementación nueva. Si eso sucede, la aplicación se bloquea en un estado interrumpido hasta que implemente una actualización adicional.