Compartilhar via


Arquivos estáticos Blazor Hybrid do ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para a versão atual, consulte a versão .NET 9 deste artigo.

Este artigo descreve como consumir arquivos de ativos estáticos em aplicativos Blazor Hybrid.

Em um aplicativo Blazor Hybrid, os arquivos estáticos são recursos de aplicativo, acessados por componentes Razor usando as seguintes abordagens:

Quando os ativos estáticos são usados apenas nos componentes Razor, os ativos estáticos podem ser consumidos da web raíz (pasta wwwroot) da mesma forma que os aplicativosBlazor WebAssembly e Blazor Server. Para obter mais informações, consulte a seção Ativos estáticos limitados a componentes Razor.

.NET MAUI

Em aplicativos .NET MAUI, osativos brutos que usam a ação de compilação MauiAsset e .NET MAUI file system helpers são usados para ativos estáticos.

Observação

Interfaces, classes e tipos de suporte para trabalhar com o armazenamento em dispositivos em todas as plataformas com suporte para recursos como escolher um arquivo, salvar preferências e utilizar o armazenamento seguro estão no namespace Microsoft.Maui.Storage. O namespace está disponível em um aplicativo MAUI Blazor Hybrid, portanto, não existe a necessidade de especificar uma instrução using em uma classe de arquivo ou uma diretiva @usingRazor em um componente Razor para o namespace.

Coloque ativos brutos na pasta Resources/Raw do aplicativo. O exemplo nesta seção usa um arquivo de texto estático.

Resources/Raw/Data.txt:

This is text from a static text file resource.

O seguinte componente Razor:

Pages/StaticAssetExample.razor:

@page "/static-asset-example"
@using System.IO
@using Microsoft.Extensions.Logging
@inject ILogger<StaticAssetExample> Logger

<h1>Static Asset Example</h1>

<p>@dataResourceText</p>

@code {
    public string dataResourceText = "Loading resource ...";

    protected override async Task OnInitializedAsync()
    {
        try
        {
            using var stream = 
                await FileSystem.OpenAppPackageFileAsync("Data.txt");
            using var reader = new StreamReader(stream);

            dataResourceText = await reader.ReadToEndAsync();
        }
        catch (FileNotFoundException ex)
        {
            dataResourceText = "Data file not found.";
            Logger.LogError(ex, "'Resource/Raw/Data.txt' not found.");
        }
    }
}

Para saber mais, consulte os recursos a seguir:

WPF

Coloque o ativo em uma pasta do aplicativo, normalmente na raiz do projeto, como uma pasta Resources. O exemplo nesta seção usa um arquivo de texto estático.

Resources/Data.txt:

This is text from a static text file resource.

Se uma pasta Properties não existir no aplicativo, crie uma pasta Properties na raiz do aplicativo.

Se a pasta Properties não contiver um arquivo de recursos (Resources.resx), crie o arquivo no Gerenciador de Soluções com o comando de menu contextual Adicionar>Novo Item.

Clique duas vezes no arquivo Resource.resx.

Selecione Cadeia de caracteres>Arquivos na lista suspensa.

Selecione Adicionar recurso>Adicionar arquivo existente. Se solicitado pelo Visual Studio a confirmar a edição do arquivo, selecione Sim. Navegue até a pasta Resources, selecione o arquivo Data.txt e selecione Abrir.

No componente de exemplo a seguir, ResourceManager.GetString obtém o texto do recurso de cadeia de caracteres para exibição.

Aviso

Nunca use métodos ResourceManager com dados não confiáveis.

StaticAssetExample.razor:

@page "/static-asset-example"
@using System.Resources

<h1>Static Asset Example</h1>

<p>@dataResourceText</p>

@code {
    public string dataResourceText = "Loading resource ...";

    protected override void OnInitialized()
    {
        var resources = 
            new ResourceManager(typeof(WpfBlazor.Properties.Resources));

        dataResourceText = resources.GetString("Data") ?? "'Data' not found.";
    }
}

Windows Forms

Coloque o ativo em uma pasta do aplicativo, normalmente na raiz do projeto, como uma pasta Resources. O exemplo nesta seção usa um arquivo de texto estático.

Resources/Data.txt:

This is text from a static text file resource.

Analise os arquivos associados a Form1 no Gerenciador de Soluções. Se Form1 não tiver um arquivo de recurso (.resx), adicione um arquivo Form1.resx com o comando de menu contextual Adicionar>Novo Item.

Clique duas vezes no arquivo Form1.resx.

Selecione Cadeia de caracteres>Arquivos na lista suspensa.

Selecione Adicionar recurso>Adicionar arquivo existente. Se solicitado pelo Visual Studio a confirmar a edição do arquivo, selecione Sim. Navegue até a pasta Resources, selecione o arquivo Data.txt e selecione Abrir.

O componente de exemplo a seguir:

  • WinFormsBlazor é o nome de assembly do aplicativo. O nome base de ResourceManager é definido como o nome do assembly de Form1 (WinFormsBlazor.Form1).
  • ResourceManager.GetString obtém o texto do recurso de cadeia de caracteres para exibição.

Aviso

Nunca use métodos ResourceManager com dados não confiáveis.

StaticAssetExample.razor:

@page "/static-asset-example"
@using System.Resources

<h1>Static Asset Example</h1>

<p>@dataResourceText</p>

@code {
    public string dataResourceText = "Loading resource ...";

    protected override async Task OnInitializedAsync()
    {   
        var resources = 
            new ResourceManager("WinFormsBlazor.Form1", this.GetType().Assembly);

        dataResourceText = resources.GetString("Data") ?? "'Data' not found.";
    }
}

Ativos estáticos limitados a componentes Razor

Um controle BlazorWebView tem um arquivo de host configurado (HostPage), em geral wwwroot/index.html. O caminho HostPage se refere ao projeto. Todos os ativos estáticos da Web (scripts, arquivos CSS, imagens e outros arquivos) referidos de um BlazorWebView são relativos ao HostPage configurado.

Os ativos estáticos da Web de uma Razor biblioteca de classes (RCL) usam caminhos especiais: _content/{PACKAGE ID}/{PATH AND FILE NAME}. O espaço reservado {PACKAGE ID} é a ID do pacote da biblioteca. A ID do pacote terá como valor padrão o nome do assembly do projeto, se <PackageId> não for especificado no arquivo de projeto. O espaço reservado {PATH AND FILE NAME} é o caminho e o nome do arquivo em wwwroot. Esses caminhos são subcaminhos da pasta do aplicativo wwwroot de forma lógica, embora realmente tenham vindo de outros pacotes ou projetos. Os grupos de estilo CSS específicos do componente também são criados na raiz da pasta wwwroot.

A raiz da web do HostPage determina qual subconjunto de ativos estáticos está disponível:

  • wwwroot/index.html (recomendado): todos os ativos na pasta wwwroot do aplicativo estão disponíveis (por exemplo: wwwroot/image.png está disponível em /image.png), incluindo subpastas (por exemplo: wwwroot/subfolder/image.png está disponível em /subfolder/image.png). Os ativos estáticos de RCL na pasta wwwroot do RCL estão disponíveis (por exemplo: wwwroot/image.png está disponível em _content/{PACKAGE ID}/image.png), incluindo subpastas (por exemplo: wwwroot/subfolder/image.png está disponível em _content/{PACKAGE ID}/subfolder/image.png).
  • wwwroot/{PATH}/index.html: todos os ativos na pasta wwwroot/{PATH} do aplicativo estão disponíveis usando caminhos relativos da raiz da Web do aplicativo. Os ativos estáticos da RCL em wwwroot/{PATH} não estão disponíveis porque estariam em um local teórico inexistente, como ../../_content/{PACKAGE ID}/{PATH}, que não é um caminho relativo com suporte.
  • wwwroot/_content/{PACKAGE ID}/index.html: todos os ativos na pasta wwwroot/{PATH} de RCL estão disponíveis usando caminhos relativos da raiz da Web de RCL. Os ativos estáticos do aplicativo em wwwroot/{PATH} não estão disponíveis porque estariam em um local teórico inexistente, como ../../{PATH}, que não é um caminho relativo suportado.

Para a maioria dos aplicativos, recomendamos colocar o HostPage na raiz da pasta wwwroot do aplicativo, que oferece a maior flexibilidade para fornecer ativos estáticos do aplicativo, RCLs e por meio de subpastas do aplicativo e RCLs.

Os exemplos a seguir mostram a referência a ativos estáticos da raiz da Web do aplicativo (pasta wwwroot) com um HostPage raiz na pasta wwwroot.

wwwroot/data.txt:

This is text from a static text file resource.

wwwroot/scripts.js:

export function showPrompt(message) {
  return prompt(message, 'Type anything here');
}

A imagem do Jeep a® seguir também é usada no exemplo desta seção. É possível clicar com o botão direito do mouse na imagem a seguir para salvá-la localmente e usar em um aplicativo de teste local.

wwwroot/jeep-yj.png:

Jeep YJ®

Em um componente Razor:

StaticAssetExample2.razor:

@page "/static-asset-example-2"
@using Microsoft.Extensions.Logging
@implements IAsyncDisposable
@inject IJSRuntime JS
@inject ILogger<StaticAssetExample2> Logger

<h1>Static Asset Example 2</h1>

<h2>Read a file</h2>

<p>@dataResourceText</p>

<h2>Call JavaScript</h2>

<p>
    <button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>

<p>@result</p>

<h2>Show an image</h2>

<p><img alt="1991 Jeep YJ" src="/jeep-yj.png" /></p>

<p>
    <em>Jeep</em> and <em>Jeep YJ</em> are registered trademarks of 
    <a href="https://www.stellantis.com">FCA US LLC (Stellantis NV)</a>.
</p>

@code {
    private string dataResourceText = "Loading resource ...";
    private IJSObjectReference? module;
    private string result;

    protected override async Task OnInitializedAsync()
    {   
        try
        {
            dataResourceText = await ReadData();
        }
        catch (FileNotFoundException ex)
        {
            dataResourceText = "Data file not found.";
            Logger.LogError(ex, "'wwwroot/data.txt' not found.");
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./scripts.js");
        }
    }

    private async Task TriggerPrompt()
    {
        result = await Prompt("Provide some text");
    }

    public async ValueTask<string> Prompt(string message) =>
        module is not null ?
            await module.InvokeAsync<string>("showPrompt", message) : null;

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

Em aplicativos .NET MAUI, adicione o seguinte método ReadData ao bloco @code do componente anterior:

private async Task<string> ReadData()
{
    using var stream = await FileSystem.OpenAppPackageFileAsync("wwwroot/data.txt");
    using var reader = new StreamReader(stream);

    return await reader.ReadToEndAsync();
}

Em aplicativos WPF e Windows Forms, adicione o seguinte método ReadData ao bloco @code do componente anterior:

private async Task<string> ReadData()
{
    using var reader = new StreamReader("wwwroot/data.txt");

    return await reader.ReadToEndAsync();
}

Os arquivos JavaScript colocados também podem ser acessados em subcaminhos lógicos do wwwroot. Em vez de usar o script descrito anteriormente para a função showPrompt no wwwroot/scripts.js, o arquivo JavaScript colocado a seguir para o componente StaticAssetExample2 também disponibiliza a função.

Pages/StaticAssetExample2.razor.js:

export function showPrompt(message) {
  return prompt(message, 'Type anything here');
}

Modifique a referência de objeto do módulo StaticAssetExample2no componente para usar o caminho do arquivo JavaScript colocado (./Pages/StaticAssetExample2.razor.js):

module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./Pages/StaticAssetExample2.razor.js");

Marcas comerciais

Jeep e Jeep YJ são marcas registradas da FCA US LLC (Stellantis NV).

Recursos adicionais