Compartilhar via


Compartilhar ativos entre clientes web e nativos usando uma RCL (biblioteca de classes) Razor

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 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 informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Use uma RCL (biblioteca de classes) Razor para compartilhar componentes Razor, código C# e ativos estáticos em projetos de cliente Web e nativos.

Este artigo baseia-se nos conceitos gerais encontrados nos seguintes artigos:

Os exemplos deste artigo compartilham ativos entre um aplicativo Blazor no servidor e um aplicativo .NET MAUIBlazor Hybrid na mesma solução:

  • Embora um aplicativo Blazor no servidor seja usado, as diretrizes se aplicam igualmente aos aplicativos Blazor WebAssembly que compartilham ativos com um aplicativo Blazor Hybrid.
  • Os projetos estão na mesma solução, mas uma RCL pode fornecer ativos compartilhados para projetos fora de uma solução.
  • A RCL é adicionada como um projeto à solução, mas qualquer RCL pode ser publicada como um pacote NuGet. Um pacote NuGet pode fornecer ativos compartilhados para projetos de cliente Web e nativos.
  • A ordem em que os projetos são criados não é importante. No entanto, projetos que dependem de uma RCL para ativos devem criar uma referência de projeto à RCL após a criação da RCL.

Para obter orientações sobre a criação de uma RCL, consulte Consumir componentes Razor do ASP.NET Core de uma RCL (biblioteca de classes) Razor. Opcionalmente, acesse as diretrizes adicionais sobre RCLs que se aplicam amplamente a aplicativos ASP.NET Core na Interface do usuário Razor reutilizável em bibliotecas de classes com ASP.NET Core.

Estruturas de destino para implantações do ClickOnce

Para publicar um projeto WPF ou Windows Forms com uma RCL (biblioteca de classes) Razor no .NET 6 com ClickOnce, a RCL deve ter net6.0-windows como destino, além de net6.0.

Exemplo:

<TargetFrameworks>net6.0;net6.0-windows</TargetFrameworks>

Para obter mais informações, consulte os seguintes artigos:

Compartilhar componentes da interface do usuário Razor da Web, código e ativos estáticos

Os componentes de uma RCL podem ser compartilhados simultaneamente por aplicativos cliente web e nativos criados usando Blazor. As diretrizes em Consumir componentes ASP.NET Core Razor de uma biblioteca de classes (RCL) Razor explicam como compartilhar componentes Razor usando uma RCL (biblioteca de classes) Razor. As mesmas diretrizes se aplicam à reutilização de componentes Razor de uma RCL em um aplicativo Blazor Hybrid.

Os namespaces de componente são derivados da ID do pacote ou do nome do assembly da RCL e do caminho da pasta do componente na RCL. Para mais informações, confira osComponentes Razor do ASP.NET Core. As diretivas @using podem ser colocadas em arquivos _Imports.razor para componentes e código, como demonstra o exemplo a seguir para uma RCL chamada SharedLibrary com uma pasta Shared de componentes Razor compartilhados e uma pasta Data de classes de dados compartilhadas:

@using SharedLibrary
@using SharedLibrary.Shared
@using SharedLibrary.Data

Coloque ativos estáticos compartilhados na pasta wwwroot da RCL e atualize caminhos de ativo estático no aplicativo para usar o seguinte formato de caminho:

_content/{PACKAGE ID/ASSEMBLY NAME}/{PATH}/{FILE NAME}

Espaços reservados:

  • {PACKAGE ID/ASSEMBLY NAME}: a ID do pacote ou o nome do assembly da RCL.
  • {PATH}: caminho opcional dentro da pasta wwwroot da RCL.
  • {FILE NAME}: o nome do arquivo do ativo estático.

O formato de caminho anterior também é usado no aplicativo para ativos estáticos fornecidos por um pacote NuGet adicionado à RCL.

Para uma RCL nomeada SharedLibrary e usando a folha de estilos Bootstrap minimizada como exemplo:

_content/SharedLibrary/css/bootstrap/bootstrap.min.css

Para obter informações adicionais sobre como compartilhar ativos estáticos entre projetos, consulte os seguintes artigos:

O arquivo raiz index.html geralmente é específico do aplicativo e deve permanecer no aplicativo Blazor Hybrid ou Blazor WebAssembly. O arquivo index.html normalmente não é compartilhado.

O componente raiz Razor (App.razor ou Main.razor) pode ser compartilhado, mas geralmente pode precisar ser específico para o aplicativo de hospedagem. Por exemplo, App.razor é diferente nos modelos de projeto Blazor no servidor e Blazor WebAssembly quando a autenticação está habilitada. Você pode adicionar o parâmetro AdditionalAssemblies para especificar o local de qualquer componente roteável compartilhado e especificar um componente de layout padrão compartilhado para o roteador por nome de tipo.

Fornecer código e serviços independentemente do modelo de hospedagem

Quando o código difere entre modelos de hospedagem ou plataformas de destino, abstraia o código como interfaces e injete as implementações de serviço em cada projeto.

O exemplo de dados meteorológicos a seguir abstrai diferentes implementações do serviço de previsão do tempo:

  • Usando uma solicitação HTTP para Blazor Hybrid e Blazor WebAssembly.
  • Como solicitar dados diretamente para um aplicativo Blazor no servidor.

O exemplo usa as seguintes especificações e convenções:

  • A RCL é nomeada SharedLibrary e contém as seguintes pastas e namespaces:
    • Data: contém a classe WeatherForecast, que serve como um modelo para dados meteorológicos.
    • Interfaces: contém a interface de serviço para as implementações de serviço, nomeada IWeatherForecastService.
  • O componente FetchData é mantido na pasta Pages da RCL, que é roteável por qualquer aplicativo que consome a RCL.
  • Cada aplicativo Blazor mantém uma implementação de serviço que implementa a interface IWeatherForecastService.

Data/WeatherForecast.cs na RCL:

namespace SharedLibrary.Data;

public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    public string? Summary { get; set; }
}

Interfaces/IWeatherForecastService.cs na RCL:

using SharedLibrary.Data;

namespace SharedLibrary.Interfaces;

public interface IWeatherForecastService
{
    Task<WeatherForecast[]?> GetForecastAsync(DateTime startDate);
}

O arquivo _Imports.razor na RCL inclui os seguintes namespaces adicionados:

@using SharedLibrary.Data
@using SharedLibrary.Interfaces

Services/WeatherForecastService.cs nos aplicativos Blazor Hybrid e Blazor WebAssembly:

using System.Net.Http.Json;
using SharedLibrary.Data;
using SharedLibrary.Interfaces;

namespace {APP NAMESPACE}.Services;

public class WeatherForecastService : IWeatherForecastService
{
    private readonly HttpClient http;

    public WeatherForecastService(HttpClient http)
    {
        this.http = http;
    }

    public async Task<WeatherForecast[]?> GetForecastAsync(DateTime startDate) =>
        await http.GetFromJsonAsync<WeatherForecast[]?>("WeatherForecast");
}

No exemplo anterior, o espaço reservado {APP NAMESPACE} é o namespace do aplicativo.

Services/WeatherForecastService.cs no aplicativo Blazor no servidor:

using SharedLibrary.Data;
using SharedLibrary.Interfaces;

namespace {APP NAMESPACE}.Services;

public class WeatherForecastService : IWeatherForecastService
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot"
    };

    public async Task<WeatherForecast[]?> GetForecastAsync(DateTime startDate) =>
        await Task.FromResult(Enumerable.Range(1, 5)
            .Select(index => new WeatherForecast
            {
                Date = startDate.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            }).ToArray());
}

No exemplo anterior, o espaço reservado {APP NAMESPACE} é o namespace do aplicativo.

Os aplicativos Blazor Hybrid, Blazor WebAssembly e Blazor no servidor registram as respectivas implementações de serviço de previsão do tempo (Services.WeatherForecastService) para IWeatherForecastService.

O projeto Blazor WebAssembly também registra um HttpClient. O HttpClient registrado em um aplicativo criado a partir do modelo de projeto Blazor WebAssembly é suficiente para essa finalidade. Para obter mais informações, consulte Chame uma API Web de um Blazoraplicativo ASP.NET Core.

Pages/FetchData.razor na RCL:

@page "/fetchdata"
@inject IWeatherForecastService ForecastService

<PageTitle>Weather forecast</PageTitle>

<h1>Weather forecast</h1>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
}

Recursos adicionais