Partilhar via


Integre componentes do ASP.NET Core Razor com MVC ou Páginas Razor em soluções Blazor WebAssembly hospedadas

Observação

As soluções hospedadas Blazor WebAssembly permanecem com suporte, mas o modelo de projeto foi removido e não é mais suportado no .NET 8 ou posterior. Este artigo aparece no sumário até ao .NET 7 para referência, mas observe que o .NET 7 é uma versão de Termo de Suporte Padrão, que já não é suportada.

Advertência

Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core.

Este artigo explica Razor os cenários de integração de componentes para aplicações hospedadas Blazor WebAssembly, incluindo a pré-renderização dos componentes Razor no servidor.

Importante

As alterações de estrutura nas versões ASP.NET Core levaram a diferentes conjuntos de instruções neste artigo. Antes de usar as diretrizes deste artigo, confirme se o seletor de versão do documento na parte superior deste artigo corresponde à versão do ASP.NET Core que você pretende usar para seu aplicativo.

A pré-renderização pode melhorar a Otimização para Motores de Busca (SEO) ao renderizar conteúdo para a resposta HTTP inicial que os motores de busca podem usar para calcular o ranking da página.

Configuração da solução

Configuração de pré-renderização

Para configurar a pré-renderização para uma aplicação hospedada Blazor WebAssembly :

  1. Hospede o Blazor WebAssembly aplicativo em um aplicativo ASP.NET Core. Uma aplicação autónoma Blazor WebAssembly pode ser adicionada a uma solução ASP.NET Core ou pode usar uma aplicação hospedada Blazor WebAssembly criada a partir do Blazor WebAssembly modelo de projeto com a opção hospedada:

    • Visual Studio: Na caixa de diálogo Informações adicionais , marque a caixa de seleção ASP.NET Core Hosted ao criar o Blazor WebAssembly aplicativo. Nos exemplos deste artigo, a solução é denominada BlazorHosted.
    • Shell de comandos da CLI do Visual Studio Code/.NET: dotnet new blazorwasm -ho (use a opção -ho|--hosted). Use a -o|--output {LOCATION} opção para criar uma pasta para a solução e definir os namespaces de projeto da solução. Nos exemplos deste artigo, a solução é denominada BlazorHosted (dotnet new blazorwasm -ho -o BlazorHosted).

    Para os exemplos neste artigo, o nome da solução hospedada (nome do assembly) é BlazorHosted. O namespace do projeto cliente é BlazorHosted.Client, e o namespace do projeto do servidor é BlazorHosted.Server.

  2. Exclua o wwwroot/index.htmlBlazor WebAssemblyClient arquivo do projeto.

  3. Client No projeto, exclua as seguintes linhas emProgram.cs:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  4. Adicione o ficheiro _Host.cshtml à pasta do projeto ServerPages. Você pode obter os arquivos de um projeto criado a partir do modelo Blazor Server usando o Visual Studio ou usando o CLI do .NET com o dotnet new blazorserver -o BlazorServer comando em um shell de comando (a opção -o BlazorServer cria uma pasta para o projeto). Depois de colocar os arquivos na Server pasta do Pages projeto, faça as seguintes alterações nos arquivos.

    Faça as seguintes alterações no _Host.cshtml arquivo:

    • Atualize o Pages namespace na parte superior do arquivo para corresponder ao namespace das Server páginas do aplicativo. O {APP NAMESPACE} marcador de posição no exemplo seguinte representa o namespace das páginas da aplicação doadora que forneceu o ficheiro _Host.cshtml.

      Suprimir.

      - @namespace {APP NAMESPACE}.Pages
      

      Adicione:

      @namespace BlazorHosted.Server.Pages
      
    • Adicione uma diretiva @using para o projeto Client na parte superior do arquivo:

      @using BlazorHosted.Client
      
    • Atualize os links de folha de estilo para apontar para as folhas de estilo do projeto WebAssembly. No exemplo a seguir, o namespace do projeto cliente é BlazorHosted.Client. O espaço reservado {APP NAMESPACE} representa o namespace da aplicação doadora que forneceu o ficheiro _Host.cshtml. Atualize o Auxiliar de Tag do Componente (<component>) do componente HeadOutlet para pré-renderizar.

      Suprimir.

      - <link href="css/site.css" rel="stylesheet" />
      - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" />
      - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      Adicione:

      <link href="css/app.css" rel="stylesheet" />
      <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
      <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
      

      Observação

      Deixe o <link> elemento que solicita a folha de estilo do Bootstrap (css/bootstrap/bootstrap.min.css) no lugar.

    • Atualize a origem do Blazor script para usar o script do lado Blazor WebAssembly do cliente:

      Suprimir.

      - <script src="_framework/blazor.server.js"></script>
      

      Adicione:

      <script src="_framework/blazor.webassembly.js"></script>
      
    • Atualize o render-mode do Auxiliar de Tag de Componente para pré-renderizar o componente raiz App com WebAssemblyPrerendered:

      Suprimir.

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      

      Adicione:

      <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      

      Importante

      A pré-renderização não é suportada para endpoints de autenticação (segmento de caminho /authentication/). Para obter mais informações, consulte ASP.NET Core Blazor WebAssembly cenários de segurança adicionais.

  5. Program.cs No ficheiro do projeto Server, altere o endpoint de fallback do ficheiro index.html para a página _Host.cshtml.

    Suprimir.

    - app.MapFallbackToFile("index.html");
    

    Adicione:

    app.MapFallbackToPage("/_Host");
    
  6. Se os projetos Client e Server usarem um ou mais serviços comuns durante a pré-renderização, fatore os registros de serviço em um método que pode ser chamado de ambos os projetos. Para obter mais informações, consulte injeção de dependência do ASP.NET CoreBlazor.

  7. Execute o projeto Server. O aplicativo Blazor WebAssembly hospedado é pré-renderizado pelo projeto Server para clientes.

Configuração para incorporar Razor componentes em páginas ou vistas

As secções e exemplos a seguir para integrar Razor componentes da aplicação ClientBlazor WebAssembly em páginas ou vistas da aplicação servidor exigem configuração adicional.

O Server projeto deve ter os seguintes arquivos e pastas.

Razor Páginas:

  • Pages/Shared/_Layout.cshtml
  • Pages/Shared/_Layout.cshtml.css
  • Pages/_ViewImports.cshtml
  • Pages/_ViewStart.cshtml

MVC:

  • Views/Shared/_Layout.cshtml
  • Views/Shared/_Layout.cshtml.css
  • Views/_ViewImports.cshtml
  • Views/_ViewStart.cshtml

Os arquivos anteriores podem ser obtidos gerando um aplicativo a partir dos modelos de projeto ASP.NET Core usando:

  • Novas ferramentas de criação de projetos do Visual Studio.
  • Abrir um shell de comando e executar dotnet new webapp -o {PROJECT NAME} (Razor Pages) ou dotnet new mvc -o {PROJECT NAME} (MVC). A opção -o|--output com um valor para o espaço reservado {PROJECT NAME} fornece um nome para o aplicativo e cria uma pasta para o aplicativo.

Atualize os namespaces no arquivo importado _ViewImports.cshtml para corresponder àqueles em uso pelo Server projeto que recebe os arquivos.

Pages/_ViewImports.cshtml (Razor Páginas):

@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Views/_ViewImports.cshtml (MVC):

@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Atualize o arquivo de layout importado, que é Pages/Shared/_Layout.cshtml para Razor Pages ou Views/Shared/_Layout.cshtml MVC.

Primeiro, exclua o título e a folha de estilo do projeto doador, que está RPDonor.styles.css no exemplo a seguir. O {PROJECT NAME} espaço reservado representa o nome do aplicativo do projeto doador.

- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />

Inclua os Client estilos do projeto no arquivo de layout. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client. O <title> elemento pode ser atualizado ao mesmo tempo.

Coloque as seguintes linhas no conteúdo do ficheiro de layout:

<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />

O layout importado contém dois Home (Index página) e Privacy links de navegação. Para fazer com que os Home links apontem para o aplicativo hospedado Blazor WebAssembly , altere os hiperlinks:

- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Em um arquivo de layout MVC:

- <a class="navbar-brand" asp-area="" asp-controller="Home" 
-     asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home" 
-     asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Atualize o nome do aplicativo do <footer> elemento. O exemplo a seguir usa o nome BlazorHosteddo aplicativo :

- &copy; {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>

No exemplo anterior, o espaço reservado {DATE} representa a data de direitos autorais em um aplicativo gerado a partir do Razor modelo de projeto Pages ou MVC.

Para fazer com que o Privacy link leve a uma página de privacidade (Razor Páginas), adicione uma página de privacidade ao Server projeto.

Pages/Privacy.cshtml no projeto Server:

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

Para uma exibição de privacidade baseada em MVC, crie uma exibição de privacidade no Server projeto.

View/Home/Privacy.cshtml no projeto Server:

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

Home No controlador do aplicativo MVC, retorne a exibição.

Adicione o seguinte código ao Controllers/HomeController.cs:

public IActionResult Privacy()
{
    return View();
}

Se você importar arquivos de um aplicativo doador, certifique-se de atualizar todos os namespaces nos arquivos para corresponder ao Server do projeto (por exemplo, BlazorHosted.Server).

Importe os ativos estáticos para o projeto Server a partir da pasta wwwroot do projeto doador:

  • wwwroot/css pasta e conteúdos
  • wwwroot/js pasta e conteúdos
  • wwwroot/lib pasta e conteúdos

Se o projeto doador for criado a partir de um modelo de projeto ASP.NET Core e os arquivos não forem modificados, você poderá copiar toda wwwroot a pasta do projeto doador para o Server projeto e remover o favicon arquivo de ícone.

Advertência

Evite colocar o ativo estático nas Client pastas e Serverwwwroot . Se o mesmo arquivo estiver presente em ambas as pastas, uma exceção será lançada porque os ativos estáticos compartilham o mesmo caminho raiz da Web. Portanto, hospede um ativo estático em qualquer uma das wwwroot pastas, não em ambas.

Depois de adotar a configuração anterior, incorpore componentes Razor em páginas ou vistas do projeto Server. Use as orientações nas seguintes seções deste artigo:

  • Renderizar componentes numa página ou vista com o Auxiliar de Etiquetas de Componente
  • Renderizar componentes numa página ou visualização com um seletor CSS

Renderizar componentes em uma página ou exibição com o Auxiliar de Tag de Componente

Depois de configurar a solução, incluindo a configuração adicional, o Auxiliar de Tag de Componente suporta dois modos de renderização para renderizar um componente de um Blazor WebAssembly aplicativo em uma página ou exibição:

No seguinte exemplo das Razor Páginas, o componente Counter é renderizado numa página. Para tornar o componente interativo, o Blazor WebAssembly script é incluído na seção de renderização da página. Para evitar usar o namespace completo para o componente Counter com o Component Tag Helper ({ASSEMBLY NAME}.Pages.Counter), adicione uma diretiva @using para o namespace do projeto cliente Pages. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client.

No projeto Server, Pages/RazorPagesCounter1.cshtml:

@page
@using BlazorHosted.Client.Pages

<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Execute o projeto Server. Navegue até a página Razor no /razorpagescounter1. O componente pré-renderizado Counter é incorporado na página.

RenderMode Configura se o componente:

  • É pré-renderizado na página.
  • É renderizado como HTML estático na página ou se inclui as informações necessárias para inicializar um Blazor aplicativo a partir do agente do usuário.

Para obter mais informações sobre o Auxiliar de Tag de Componente, incluindo parâmetros de passagem e RenderMode configuração, consulte Auxiliar de Tag de Componente no ASP.NET Core.

Trabalho adicional pode ser necessário dependendo dos recursos estáticos que os componentes usam e como as páginas de layout são organizadas em um aplicativo. Normalmente, os scripts são adicionados à seção de renderização de uma página ou de uma exibição Scripts, e as folhas de estilo <head> são adicionadas ao conteúdo do elemento do layout.

Definir conteúdo filho por meio de um fragmento de renderização

O Auxiliar de Tag de Componente não suporta receber um RenderFragment delegado para o conteúdo de filho (por exemplo, param-ChildContent="..."). Recomendamos criar um componente Razor (.razor) que faça referência ao componente que desejas renderizar, juntamente com o conteúdo filho que queres passar. Em seguida, invoca o componente Razor da página ou visão.

Certifique-se de que os componentes pré-renderizados de nível superior não sejam cortados na publicação

Se um Auxiliar de Tag de Componente fizer referência direta a um componente de uma biblioteca que está sujeito a remoção no processo de publicação, o componente poderá ser removido durante a publicação porque não há referências a ele a partir do código do aplicativo cliente. Como resultado, o componente não é pré-renderizado, deixando um ponto em branco na saída. Se isso ocorrer, instrua o trimmer a preservar o componente de biblioteca ao adicionar um atributo DynamicDependency a qualquer classe na aplicação cliente. Para preservar um componente chamado SomeLibraryComponentToBePreserved, adicione o seguinte a qualquer componente:

@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All, 
    typeof(SomeLibraryComponentToBePreserved))]

A abordagem anterior geralmente não é necessária porque o aplicativo geralmente pré-renderiza seus componentes (que não são cortados), o que, por sua vez, faz referência a componentes de bibliotecas (fazendo com que eles também não sejam cortados). Use DynamicDependency explicitamente apenas para pré-renderizar um componente de biblioteca diretamente quando a biblioteca estiver sujeita a otimização.

Renderizar componentes numa página ou visualização com um seletor CSS

Depois de configurar a solução, incluindo a configuração adicional, adicione componentes raiz ao Client projeto de uma solução hospedada Blazor WebAssembly no arquivo Program.cs. No exemplo a seguir, o componente Counter é declarado como um componente raiz com um seletor CSS que seleciona o elemento cujo id corresponde a counter-component. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client.

No arquivo Program.cs do projeto Client, adicione o namespace para os componentes do projeto Razor ao topo do arquivo:

using BlazorHosted.Client.Pages;

Depois que o builder for estabelecido no Program.cs, adicione o Counter componente como um componente raiz:

builder.RootComponents.Add<Counter>("#counter-component");

No seguinte exemplo das Razor Páginas, o componente Counter é renderizado numa página. Para tornar o componente interativo, o Blazor WebAssembly script é incluído na seção de renderização da página.

No projeto Server, Pages/RazorPagesCounter2.cshtml:

@page

<div id="counter-component">Loading...</div>

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Execute o projeto Server. Navegue até a página Razor no /razorpagescounter2. O componente pré-renderizado Counter é incorporado na página.

Trabalho adicional pode ser necessário dependendo dos recursos estáticos que os componentes usam e como as páginas de layout são organizadas em um aplicativo. Normalmente, os scripts são adicionados à seção de renderização de uma página ou de uma exibição Scripts, e as folhas de estilo <head> são adicionadas ao conteúdo do elemento do layout.

Observação

O exemplo anterior lança um JSException se um Blazor WebAssembly aplicativo é pré-renderizado e integrado a um Razor aplicativo Pages ou MVC simultaneamente com o uso de um seletor CSS. Navegar para um dos componentes do Client projeto Razor ou navegar para uma página ou exibição do Server com um componente incorporado lança um ou mais JSException.

Esse comportamento é normal porque a pré-renderização e a integração de um Blazor WebAssembly aplicativo com componentes roteáveis Razor são incompatíveis com o uso de seletores CSS.

Se tens trabalhado com os exemplos nas seções anteriores e desejas apenas ver o seletor CSS funcionar na tua aplicação de exemplo, comenta a especificação do componente raiz do projeto no arquivo AppClient.

- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");

Navegue até a página ou exibição com o componente incorporado Razor que usa um seletor CSS (por exemplo, /razorpagescounter2 do exemplo anterior). A página ou exibição é carregada com o componente incorporado e o componente incorporado funciona conforme o esperado.

Manter o estado pré-renderizado

Sem guardar o estado pré-renderizado, o estado utilizado durante a pré-renderização é perdido e precisa ser recriado quando a aplicação estiver totalmente carregada. Se qualquer estado for configurado de forma assíncrona, a interface do usuário poderá piscar à medida que a interface do usuário pré-renderizada for substituída por espaços reservados temporários e, em seguida, totalmente renderizada novamente.

Para persistir o estado dos componentes pré-renderizados, use o Auxiliar de Marca de Estado do Componente Persistente (fonte de referência). Adicione a etiqueta do Auxiliar de etiquetas, <persist-component-state />, dentro da etiqueta de fecho </body> na página _Host de uma aplicação que pré-renderiza componentes.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma tag para uma versão específica, use a lista suspensa Alternar entre ramificações ou tags. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Em Pages/_Host.cshtml aplicações Blazor que são WebAssembly pré-renderizadas (WebAssemblyPrerendered) numa aplicação hospedada Blazor WebAssembly :

<body>
    ...

    <persist-component-state />
</body>

Decida qual estado deve persistir usando o serviço PersistentComponentState. PersistentComponentState.RegisterOnPersisting registra uma função de retorno para persistir o estado do componente antes que a aplicação seja pausada. O estado é recuperado quando o aplicativo é retomado. Faça a chamada no final do código de inicialização para evitar uma possível condição de concorrência durante o desligamento da aplicação.

No exemplo a seguir:

  • O {TYPE} espaço reservado representa o tipo de dados a serem persistidos (por exemplo, WeatherForecast[]).
  • O {TOKEN} marcador de posição é uma cadeia de caracteres identificador de estado (por exemplo, fetchdata).
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
    private {TYPE} data;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

O exemplo a seguir é uma versão atualizada do componente FetchData em um aplicativo Blazor WebAssembly hospedado com base no modelo do projeto Blazor. O componente WeatherForecastPreserveState persiste o estado de previsão do tempo durante a pré-renderização e, em seguida, recupera esse estado para inicializar o componente. O Auxiliar de Marca de Estado do Componente Persistente persiste o estado do componente após todas as invocações de componentes.

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@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 = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            nameof(forecasts), out var restored))
        {
            forecasts = await WeatherForecastService.GetForecastAsync(
                DateOnly.FromDateTime(DateTime.Now));
        }
        else
        {
            forecasts = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

Ao inicializar componentes com o mesmo estado usado durante a pré-renderização, todas as etapas de inicialização dispendiosas são executadas apenas uma vez. A interface do usuário renderizada também corresponde à interface do usuário pré-renderizada, portanto, nenhuma cintilação ocorre no navegador.

O estado pré-renderizado persistente é transferido para o cliente, onde é usado para restaurar o estado do componente. Para pré-renderização em um aplicativo hospedado Blazor WebAssembly , os dados são expostos ao navegador e não devem conter informações confidenciais e privadas.

Recursos adicionais Blazor WebAssembly

A pré-renderização pode melhorar a Otimização para Motores de Busca (SEO) ao renderizar conteúdo para a resposta HTTP inicial que os motores de busca podem usar para calcular o ranking da página.

Configuração da solução

Configuração de pré-renderização

Para configurar a pré-renderização para uma aplicação hospedada Blazor WebAssembly :

  1. Hospede o Blazor WebAssembly aplicativo em um aplicativo ASP.NET Core. Uma aplicação autónoma Blazor WebAssembly pode ser adicionada a uma solução ASP.NET Core ou pode usar uma aplicação hospedada Blazor WebAssembly criada a partir do Blazor WebAssembly modelo de projeto com a opção hospedada:

    • Visual Studio: Na caixa de diálogo Informações adicionais , marque a caixa de seleção ASP.NET Core Hosted ao criar o Blazor WebAssembly aplicativo. Nos exemplos deste artigo, a solução é denominada BlazorHosted.
    • Shell de comandos da CLI do Visual Studio Code/.NET: dotnet new blazorwasm -ho (use a opção -ho|--hosted). Use a -o|--output {LOCATION} opção para criar uma pasta para a solução e definir os namespaces de projeto da solução. Nos exemplos deste artigo, a solução é denominada BlazorHosted (dotnet new blazorwasm -ho -o BlazorHosted).

    Para os exemplos neste artigo, o namespace do projeto cliente é BlazorHosted.Client, e o namespace do projeto do servidor é BlazorHosted.Server.

  2. Exclua o wwwroot/index.htmlBlazor WebAssemblyClient arquivo do projeto.

  3. Client No projeto, exclua as seguintes linhas emProgram.cs:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  4. Adicione _Host.cshtml e _Layout.cshtml arquivos à Server pasta do Pages projeto. Você pode obter os arquivos de um projeto criado a partir do modelo Blazor Server usando o Visual Studio ou usando o CLI do .NET com o dotnet new blazorserver -o BlazorServer comando em um shell de comando (a opção -o BlazorServer cria uma pasta para o projeto). Depois de colocar os arquivos na Server pasta do Pages projeto, faça as seguintes alterações nos arquivos.

    Importante

    O uso de uma página de layout (_Layout.cshtml) com um Auxiliar de Tag de Componente para um HeadOutlet componente é necessário para controlar <head> o conteúdo, como o título da página (PageTitle componente) e outros elementos de cabeçalho (HeadContent componente). Para obter mais informações, consulte Controlar o conteúdo do cabeçote em aplicativos ASP.NET CoreBlazor.

    Faça as seguintes alterações no _Layout.cshtml arquivo:

    • Atualize o Pages namespace na parte superior do arquivo para corresponder ao namespace das Server páginas do aplicativo. O {APP NAMESPACE} marcador de posição no exemplo seguinte representa o namespace das páginas da aplicação doadora que forneceu o ficheiro _Layout.cshtml.

      Suprimir.

      - @namespace {APP NAMESPACE}.Pages
      

      Adicione:

      @namespace BlazorHosted.Server.Pages
      
    • Adicione uma diretiva @using para o projeto Client na parte superior do arquivo:

      @using BlazorHosted.Client
      
    • Atualize os links de folha de estilo para apontar para as folhas de estilo do projeto WebAssembly. No exemplo a seguir, o namespace do projeto cliente é BlazorHosted.Client. O espaço reservado {APP NAMESPACE} representa o namespace da aplicação doadora que forneceu o ficheiro _Layout.cshtml. Atualize o Auxiliar de Tag do Componente (<component>) do componente HeadOutlet para pré-renderizar.

      Suprimir.

      - <link href="css/site.css" rel="stylesheet" />
      - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" />
      - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      Adicione:

      <link href="css/app.css" rel="stylesheet" />
      <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
      <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
      

      Observação

      Deixe o <link> elemento que solicita a folha de estilo do Bootstrap (css/bootstrap/bootstrap.min.css) no lugar.

    • Atualize a origem do Blazor script para usar o script do lado Blazor WebAssembly do cliente:

      Suprimir.

      - <script src="_framework/blazor.server.js"></script>
      

      Adicione:

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

    No ficheiro _Host.cshtml:

    • Altere o Pages namespace para o Client do projeto. O marcador de posição {APP NAMESPACE} representa o namespace das páginas da aplicação doadora que forneceu o ficheiro _Host.cshtml.

      Suprimir.

      - @namespace {APP NAMESPACE}.Pages
      

      Adicione:

      @namespace BlazorHosted.Client
      
    • Atualize o render-mode do Auxiliar de Tag de Componente para pré-renderizar o componente raiz App com WebAssemblyPrerendered:

      Suprimir.

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      

      Adicione:

      <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      

      Importante

      A pré-renderização não é suportada para endpoints de autenticação (segmento de caminho /authentication/). Para obter mais informações, consulte ASP.NET Core Blazor WebAssembly cenários de segurança adicionais.

  5. No mapeamento de ponto de extremidade do Server projeto no Program.cs, altere o fallback do index.html arquivo para a _Host.cshtml página:

    Suprimir.

    - app.MapFallbackToFile("index.html");
    

    Adicione:

    app.MapFallbackToPage("/_Host");
    
  6. Se os projetos Client e Server usarem um ou mais serviços comuns durante a pré-renderização, fatore os registros de serviço em um método que pode ser chamado de ambos os projetos. Para obter mais informações, consulte injeção de dependência do ASP.NET CoreBlazor.

  7. Execute o projeto Server. O aplicativo Blazor WebAssembly hospedado é pré-renderizado pelo projeto Server para clientes.

Configuração para incorporar Razor componentes em páginas ou vistas

As secções e exemplos a seguir para integrar Razor componentes da aplicação ClientBlazor WebAssembly em páginas ou vistas da aplicação servidor exigem configuração adicional.

O Server projeto deve ter os seguintes arquivos e pastas.

Razor Páginas:

  • Pages/Shared/_Layout.cshtml
  • Pages/Shared/_Layout.cshtml.css
  • Pages/_ViewImports.cshtml
  • Pages/_ViewStart.cshtml

MVC:

  • Views/Shared/_Layout.cshtml
  • Views/Shared/_Layout.cshtml.css
  • Views/_ViewImports.cshtml
  • Views/_ViewStart.cshtml

Importante

O uso de uma página de layout (_Layout.cshtml) com um Auxiliar de Tag de Componente para um HeadOutlet componente é necessário para controlar <head> o conteúdo, como o título da página (PageTitle componente) e outros elementos de cabeçalho (HeadContent componente). Para obter mais informações, consulte Controlar o conteúdo do cabeçote em aplicativos ASP.NET CoreBlazor.

Os arquivos anteriores podem ser obtidos gerando um aplicativo a partir dos modelos de projeto ASP.NET Core usando:

  • Novas ferramentas de criação de projetos do Visual Studio.
  • Abrir um shell de comando e executar dotnet new webapp -o {PROJECT NAME} (Razor Pages) ou dotnet new mvc -o {PROJECT NAME} (MVC). A opção -o|--output com um valor para o espaço reservado {PROJECT NAME} fornece um nome para o aplicativo e cria uma pasta para o aplicativo.

Atualize os namespaces no arquivo importado _ViewImports.cshtml para corresponder àqueles em uso pelo Server projeto que recebe os arquivos.

Pages/_ViewImports.cshtml (Razor Páginas):

@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Views/_ViewImports.cshtml (MVC):

@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Atualize o arquivo de layout importado, que é Pages/Shared/_Layout.cshtml para Razor Pages ou Views/Shared/_Layout.cshtml MVC.

Primeiro, exclua o título e a folha de estilo do projeto doador, que está RPDonor.styles.css no exemplo a seguir. O {PROJECT NAME} espaço reservado representa o nome do aplicativo do projeto doador.

- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />

Inclua os Client estilos do projeto no arquivo de layout. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client. O <title> elemento pode ser atualizado ao mesmo tempo.

Coloque as seguintes linhas no conteúdo do ficheiro de layout:

<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />

O layout importado contém dois Home (Index página) e Privacy links de navegação. Para fazer com que os Home links apontem para o aplicativo hospedado Blazor WebAssembly , altere os hiperlinks:

- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Em um arquivo de layout MVC:

- <a class="navbar-brand" asp-area="" asp-controller="Home" 
-     asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home" 
-     asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Atualize o nome do aplicativo do <footer> elemento. O exemplo a seguir usa o nome BlazorHosteddo aplicativo :

- &copy; {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>

No exemplo anterior, o espaço reservado {DATE} representa a data de direitos autorais em um aplicativo gerado a partir do Razor modelo de projeto Pages ou MVC.

Para fazer com que o Privacy link leve a uma página de privacidade (Razor Páginas), adicione uma página de privacidade ao Server projeto.

Pages/Privacy.cshtml no projeto Server:

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

Para uma exibição de privacidade baseada em MVC, crie uma exibição de privacidade no Server projeto.

View/Home/Privacy.cshtml no projeto Server:

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

Home No controlador do aplicativo MVC, retorne a exibição.

Adicione o seguinte código ao Controllers/HomeController.cs:

public IActionResult Privacy()
{
    return View();
}

Se você importar arquivos de um aplicativo doador, certifique-se de atualizar todos os namespaces nos arquivos para corresponder ao Server do projeto (por exemplo, BlazorHosted.Server).

Importe os ativos estáticos para o projeto Server a partir da pasta wwwroot do projeto doador:

  • wwwroot/css pasta e conteúdos
  • wwwroot/js pasta e conteúdos
  • wwwroot/lib pasta e conteúdos

Se o projeto doador for criado a partir de um modelo de projeto ASP.NET Core e os arquivos não forem modificados, você poderá copiar toda wwwroot a pasta do projeto doador para o Server projeto e remover o favicon arquivo de ícone.

Advertência

Evite colocar o ativo estático nas Client pastas e Serverwwwroot . Se o mesmo arquivo estiver presente em ambas as pastas, uma exceção será lançada porque o ativo estático em cada pasta compartilha o mesmo caminho raiz da Web. Portanto, hospede um ativo estático em qualquer wwwroot pasta, não em ambas.

Depois de adotar a configuração anterior, incorpore componentes Razor em páginas ou vistas do projeto Server. Use as orientações nas seguintes seções deste artigo:

  • Renderizar componentes numa página ou vista com o Auxiliar de Etiquetas de Componente
  • Renderizar componentes numa página ou visualização com um seletor CSS

Renderizar componentes em uma página ou exibição com o Auxiliar de Tag de Componente

Depois de configurar a solução, incluindo a configuração adicional, o Auxiliar de Tag de Componente suporta dois modos de renderização para renderizar um componente de um Blazor WebAssembly aplicativo em uma página ou exibição:

No seguinte exemplo das Razor Páginas, o componente Counter é renderizado numa página. Para tornar o componente interativo, o Blazor WebAssembly script é incluído na seção de renderização da página. Para evitar usar o namespace completo para o componente Counter com o Component Tag Helper ({ASSEMBLY NAME}.Pages.Counter), adicione uma diretiva @using para o namespace do projeto cliente Pages. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client.

No projeto Server, Pages/RazorPagesCounter1.cshtml:

@page
@using BlazorHosted.Client.Pages

<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Execute o projeto Server. Navegue até a página Razor no /razorpagescounter1. O componente pré-renderizado Counter é incorporado na página.

RenderMode Configura se o componente:

  • É pré-renderizado na página.
  • É renderizado como HTML estático na página ou se inclui as informações necessárias para inicializar um Blazor aplicativo a partir do agente do usuário.

Para obter mais informações sobre o Auxiliar de Tag de Componente, incluindo parâmetros de passagem e RenderMode configuração, consulte Auxiliar de Tag de Componente no ASP.NET Core.

Trabalho adicional pode ser necessário dependendo dos recursos estáticos que os componentes usam e como as páginas de layout são organizadas em um aplicativo. Normalmente, os scripts são adicionados à seção de renderização de uma página ou de uma exibição Scripts, e as folhas de estilo <head> são adicionadas ao conteúdo do elemento do layout.

Definir conteúdo filho por meio de um fragmento de renderização

O Auxiliar de Tag de Componente não suporta receber um RenderFragment delegado para o conteúdo de filho (por exemplo, param-ChildContent="..."). Recomendamos criar um componente Razor (.razor) que faça referência ao componente que desejas renderizar, juntamente com o conteúdo filho que queres passar. Em seguida, invoca o componente Razor da página ou visão.

Certifique-se de que os componentes pré-renderizados de nível superior não sejam cortados na publicação

Se um Auxiliar de Tag de Componente fizer referência direta a um componente de uma biblioteca que está sujeito a remoção no processo de publicação, o componente poderá ser removido durante a publicação porque não há referências a ele a partir do código do aplicativo cliente. Como resultado, o componente não é pré-renderizado, deixando um ponto em branco na saída. Se isso ocorrer, instrua o trimmer a preservar o componente de biblioteca ao adicionar um atributo DynamicDependency a qualquer classe na aplicação cliente. Para preservar um componente chamado SomeLibraryComponentToBePreserved, adicione o seguinte a qualquer componente:

@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All, 
    typeof(SomeLibraryComponentToBePreserved))]

A abordagem anterior geralmente não é necessária porque o aplicativo geralmente pré-renderiza seus componentes (que não são cortados), o que, por sua vez, faz referência a componentes de bibliotecas (fazendo com que eles também não sejam cortados). Use DynamicDependency explicitamente apenas para pré-renderizar um componente de biblioteca diretamente quando a biblioteca estiver sujeita a otimização.

Renderizar componentes numa página ou visualização com um seletor CSS

Depois de configurar a solução, incluindo a configuração adicional, adicione componentes raiz ao Client projeto de uma solução hospedada Blazor WebAssembly no arquivo Program.cs. No exemplo a seguir, o componente Counter é declarado como um componente raiz com um seletor CSS que seleciona o elemento cujo id corresponde a counter-component. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client.

No arquivo Program.cs do projeto Client, adicione o namespace para os componentes do projeto Razor ao topo do arquivo:

using BlazorHosted.Client.Pages;

Depois que o builder for estabelecido no Program.cs, adicione o Counter componente como um componente raiz:

builder.RootComponents.Add<Counter>("#counter-component");

No seguinte exemplo das Razor Páginas, o componente Counter é renderizado numa página. Para tornar o componente interativo, o Blazor WebAssembly script é incluído na seção de renderização da página.

No projeto Server, Pages/RazorPagesCounter2.cshtml:

@page

<div id="counter-component">Loading...</div>

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Execute o projeto Server. Navegue até a página Razor no /razorpagescounter2. O componente pré-renderizado Counter é incorporado na página.

Trabalho adicional pode ser necessário dependendo dos recursos estáticos que os componentes usam e como as páginas de layout são organizadas em um aplicativo. Normalmente, os scripts são adicionados à seção de renderização de uma página ou de uma exibição Scripts, e as folhas de estilo <head> são adicionadas ao conteúdo do elemento do layout.

Observação

O exemplo anterior lança um JSException se um Blazor WebAssembly aplicativo é pré-renderizado e integrado a um Razor aplicativo Pages ou MVC simultaneamente com o uso de um seletor CSS. Navegar para um dos componentes do Client projeto Razor ou navegar para uma página ou exibição do Server com um componente incorporado lança um ou mais JSException.

Esse comportamento é normal porque a pré-renderização e a integração de um Blazor WebAssembly aplicativo com componentes roteáveis Razor são incompatíveis com o uso de seletores CSS.

Se tens trabalhado com os exemplos nas seções anteriores e desejas apenas ver o seletor CSS funcionar na tua aplicação de exemplo, comenta a especificação do componente raiz do projeto no arquivo AppClient.

- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");

Navegue até a página ou exibição com o componente incorporado Razor que usa um seletor CSS (por exemplo, /razorpagescounter2 do exemplo anterior). A página ou exibição é carregada com o componente incorporado e o componente incorporado funciona conforme o esperado.

Manter o estado pré-renderizado

Sem guardar o estado pré-renderizado, o estado utilizado durante a pré-renderização é perdido e precisa ser recriado quando a aplicação estiver totalmente carregada. Se qualquer estado for configurado de forma assíncrona, a interface do usuário poderá piscar à medida que a interface do usuário pré-renderizada for substituída por espaços reservados temporários e, em seguida, totalmente renderizada novamente.

Para resolver esses problemas, Blazor oferece suporte à persistência do estado em uma página pré-renderizada usando o Auxiliar de Tag de Estado do Componente Persistente. Adicione a tag do Auxiliar de tag, <persist-component-state />, dentro da tag de fechamento </body> .

Pages/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

Decida qual estado deve persistir usando o serviço PersistentComponentState. PersistentComponentState.RegisterOnPersisting registra uma função de retorno para persistir o estado do componente antes que a aplicação seja pausada. O estado é recuperado quando o aplicativo é retomado. Faça a chamada no final do código de inicialização para evitar uma possível condição de concorrência durante o desligamento da aplicação.

O exemplo a seguir é uma versão atualizada do componente FetchData em um aplicativo Blazor WebAssembly hospedado com base no modelo do projeto Blazor. O componente WeatherForecastPreserveState persiste o estado de previsão do tempo durante a pré-renderização e, em seguida, recupera esse estado para inicializar o componente. O Auxiliar de Marca de Estado do Componente Persistente persiste o estado do componente após todas as invocações de componentes.

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@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 = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            nameof(forecasts), out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateTime.Now);
        }
        else
        {
            forecasts = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

Ao inicializar componentes com o mesmo estado usado durante a pré-renderização, todas as etapas de inicialização dispendiosas são executadas apenas uma vez. A interface do usuário renderizada também corresponde à interface do usuário pré-renderizada, portanto, nenhuma cintilação ocorre no navegador.

O estado pré-renderizado persistente é transferido para o cliente, onde é usado para restaurar o estado do componente. Para pré-renderização em um aplicativo hospedado Blazor WebAssembly , os dados são expostos ao navegador e não devem conter informações confidenciais e privadas.

Recursos adicionais Blazor WebAssembly

A pré-renderização pode melhorar a Otimização para Motores de Busca (SEO) ao renderizar conteúdo para a resposta HTTP inicial que os motores de busca podem usar para calcular o ranking da página.

Configuração da solução

Configuração de pré-renderização

Para configurar a pré-renderização para uma aplicação hospedada Blazor WebAssembly :

  1. Hospede o Blazor WebAssembly aplicativo em um aplicativo ASP.NET Core. Uma aplicação autónoma Blazor WebAssembly pode ser adicionada a uma solução ASP.NET Core ou pode usar uma aplicação hospedada Blazor WebAssembly criada a partir do Blazor WebAssembly modelo de projeto com a opção hospedada:

    • Visual Studio: Na caixa de diálogo Informações adicionais , marque a caixa de seleção ASP.NET Core Hosted ao criar o Blazor WebAssembly aplicativo. Nos exemplos deste artigo, a solução é denominada BlazorHosted.
    • Shell de comandos da CLI do Visual Studio Code/.NET: dotnet new blazorwasm -ho (use a opção -ho|--hosted). Use a -o|--output {LOCATION} opção para criar uma pasta para a solução e definir os namespaces de projeto da solução. Nos exemplos deste artigo, a solução é denominada BlazorHosted (dotnet new blazorwasm -ho -o BlazorHosted).

    Para os exemplos neste artigo, o namespace do projeto cliente é BlazorHosted.Client, e o namespace do projeto do servidor é BlazorHosted.Server.

  2. Exclua o wwwroot/index.htmlBlazor WebAssemblyClient arquivo do projeto.

  3. Client No projeto, exclua a seguinte linha emProgram.cs:

    - builder.RootComponents.Add<App>("#app");
    
  4. Adicione um Pages/_Host.cshtml arquivo à Server pasta do Pages projeto. Você pode obter um arquivo _Host.cshtml de um projeto criado a partir do modelo Blazor Server com o comando dotnet new blazorserver -o BlazorServer em um shell de comando (a opção -o BlazorServer cria uma pasta para o projeto). Depois de colocar o arquivo Pages/_Host.cshtml no projeto Server da solução hospedada Blazor WebAssembly, faça as seguintes alterações no arquivo:

    • Forneça uma @using diretiva para o Client projeto (por exemplo, @using BlazorHosted.Client).

    • Atualize os links de folha de estilo para apontar para as folhas de estilo do projeto WebAssembly. No exemplo a seguir, o namespace do projeto cliente é BlazorHosted.Client:

      - <link href="css/site.css" rel="stylesheet" />
      - <link href="_content/BlazorServer/_framework/scoped.styles.css" rel="stylesheet" />
      + <link href="css/app.css" rel="stylesheet" />
      + <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
      

      Observação

      Deixe o <link> elemento que solicita a folha de estilo do Bootstrap (css/bootstrap/bootstrap.min.css) no lugar.

    • Atualize o render-mode do Auxiliar de Tag de Componente para pré-renderizar o componente raiz App com WebAssemblyPrerendered:

      - <component type="typeof(App)" render-mode="ServerPrerendered" />
      + <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
      
    • Atualize a origem do Blazor script para usar o script do lado Blazor WebAssembly do cliente:

      - <script src="_framework/blazor.server.js"></script>
      + <script src="_framework/blazor.webassembly.js"></script>
      
  5. No projeto Startup.Configure, altere o fallback do ficheiro Server para a página index.html.

    Startup.cs:

    - endpoints.MapFallbackToFile("index.html");
    + endpoints.MapFallbackToPage("/_Host");
    
  6. Se os projetos Client e Server usarem um ou mais serviços comuns durante a pré-renderização, fatore os registros de serviço em um método que pode ser chamado de ambos os projetos. Para obter mais informações, consulte injeção de dependência do ASP.NET CoreBlazor.

  7. Execute o projeto Server. O aplicativo Blazor WebAssembly hospedado é pré-renderizado pelo projeto Server para clientes.

Configuração para incorporar Razor componentes em páginas ou vistas

As seções e exemplos a seguir neste artigo para incorporar Razor componentes do aplicativo cliente Blazor WebAssembly em páginas ou exibições do aplicativo servidor exigem configuração adicional.

Use um ficheiro de layout padrão Pages ou MVC no projeto RazorServer. O Server projeto deve ter os seguintes arquivos e pastas.

Razor Páginas:

  • Pages/Shared/_Layout.cshtml
  • Pages/_ViewImports.cshtml
  • Pages/_ViewStart.cshtml

MVC:

  • Views/Shared/_Layout.cshtml
  • Views/_ViewImports.cshtml
  • Views/_ViewStart.cshtml

Obtenha os ficheiros anteriores de uma aplicação criada a partir do modelo de projeto Razor Pages ou MVC. Para obter mais informações, consulte Tutorial: Introdução ao Razor Pages in ASP.NET Core ou Introdução ao ASP.NET Core MVC.

Atualize os namespaces no arquivo importado _ViewImports.cshtml para corresponder àqueles em uso pelo Server projeto que recebe os arquivos.

Atualize o arquivo de layout importado (_Layout.cshtml) para incluir os Client estilos do projeto. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client. O <title> elemento pode ser atualizado ao mesmo tempo.

Pages/Shared/_Layout.cshtml (Razor Páginas) ou Views/Shared/_Layout.cshtml (MVC):

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-   <title>@ViewData["Title"] - DonorProject</title>
+   <title>@ViewData["Title"] - BlazorHosted</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
+   <link href="css/app.css" rel="stylesheet" />
+   <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
</head>

O layout importado contém links de navegação Home e Privacy. Para fazer com que o Home link aponte para o aplicativo hospedado Blazor WebAssembly , altere o hiperlink:

- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Em um arquivo de layout MVC:

- <a class="nav-link text-dark" asp-area="" asp-controller="Home" 
-     asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>

Para fazer com que o Privacy link leve a uma página de privacidade, adicione uma página de privacidade ao Server projeto.

Pages/Privacy.cshtml no projeto Server:

@page
@model BlazorHosted.Server.Pages.PrivacyModel
@{
}

<h1>Privacy Policy</h1>

Se preferir uma visualização de privacidade baseada em MVC, crie uma exibição de privacidade no Server projeto.

View/Home/Privacy.cshtml:

@{
    ViewData["Title"] = "Privacy Policy";
}

<h1>@ViewData["Title"]</h1>

No controlador Home, retorne a visualização.

Controllers/HomeController.cs:

public IActionResult Privacy()
{
    return View();
}

Importe os ativos estáticos para o projeto Server a partir da pasta wwwroot do projeto doador:

  • wwwroot/css pasta e conteúdos
  • wwwroot/js pasta e conteúdos
  • wwwroot/lib pasta e conteúdos

Se o projeto doador for criado a partir de um modelo de projeto ASP.NET Core e os arquivos não forem modificados, você poderá copiar toda wwwroot a pasta do projeto doador para o Server projeto e remover o favicon arquivo de ícone.

Advertência

Evite colocar o ativo estático nas Client pastas e Serverwwwroot . Se o mesmo arquivo estiver presente em ambas as pastas, uma exceção será lançada porque o ativo estático em cada pasta compartilha o mesmo caminho raiz da Web. Portanto, hospede um ativo estático em qualquer wwwroot pasta, não em ambas.

Renderizar componentes em uma página ou exibição com o Auxiliar de Tag de Componente

Depois de configurar a solução, incluindo a configuração adicional, o Auxiliar de Tag de Componente suporta dois modos de renderização para renderizar um componente de um Blazor WebAssembly aplicativo em uma página ou exibição:

No seguinte exemplo das Razor Páginas, o componente Counter é renderizado numa página. Para tornar o componente interativo, o Blazor WebAssembly script é incluído na seção de renderização da página. Para evitar usar o namespace completo para o componente Counter com o Component Tag Helper ({ASSEMBLY NAME}.Pages.Counter), adicione uma diretiva @using para o namespace do projeto cliente Pages. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client.

No projeto Server, Pages/RazorPagesCounter1.cshtml:

@page
@using BlazorHosted.Client.Pages

<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Execute o projeto Server. Navegue até a página Razor no /razorpagescounter1. O componente pré-renderizado Counter é incorporado na página.

RenderMode Configura se o componente:

  • É pré-renderizado na página.
  • É renderizado como HTML estático na página ou se inclui as informações necessárias para inicializar um Blazor aplicativo a partir do agente do usuário.

Para obter mais informações sobre o Auxiliar de Tag de Componente, incluindo parâmetros de passagem e RenderMode configuração, consulte Auxiliar de Tag de Componente no ASP.NET Core.

Trabalho adicional pode ser necessário dependendo dos recursos estáticos que os componentes usam e como as páginas de layout são organizadas em um aplicativo. Normalmente, os scripts são adicionados à seção de renderização de uma página ou de uma exibição Scripts, e as folhas de estilo <head> são adicionadas ao conteúdo do elemento do layout.

Renderizar componentes numa página ou visualização com um seletor CSS

Depois de configurar a solução, incluindo a configuração adicional, adicione componentes raiz ao Client projeto de uma solução hospedada Blazor WebAssembly no Program.cs. No exemplo a seguir, o componente Counter é declarado como um componente raiz com um seletor CSS que seleciona o elemento cujo id corresponde a counter-component. No exemplo a seguir, o Client namespace do projeto é BlazorHosted.Client.

No âmbito do Program.cs do projeto, adicione o namespace Client para os componentes Razor do projeto no topo do arquivo.

using BlazorHosted.Client.Pages;

Depois que o builder for estabelecido no Program.cs, adicione o Counter componente como um componente raiz:

builder.RootComponents.Add<Counter>("#counter-component");

No seguinte exemplo das Razor Páginas, o componente Counter é renderizado numa página. Para tornar o componente interativo, o Blazor WebAssembly script é incluído na seção de renderização da página.

No projeto Server, Pages/RazorPagesCounter2.cshtml:

@page

<div id="counter-component">Loading...</div>

@section Scripts {
    <script src="_framework/blazor.webassembly.js"></script>
}

Execute o projeto Server. Navegue até a página Razor no /razorpagescounter2. O componente pré-renderizado Counter é incorporado na página.

Trabalho adicional pode ser necessário dependendo dos recursos estáticos que os componentes usam e como as páginas de layout são organizadas em um aplicativo. Normalmente, os scripts são adicionados à seção de renderização de uma página ou de uma exibição Scripts, e as folhas de estilo <head> são adicionadas ao conteúdo do elemento do layout.

Observação

O exemplo anterior lança um JSException se um Blazor WebAssembly aplicativo é pré-renderizado e integrado a um Razor aplicativo Pages ou MVC simultaneamente com um seletor CSS. Navegar para um dos componentes do Client projeto Razor gera a seguinte exceção:

Microsoft.JSInterop.JSException: Não foi possível encontrar nenhum elemento correspondente ao seletor '#counter-component'.

Esse comportamento é normal porque a pré-renderização e a integração de um Blazor WebAssembly aplicativo com componentes roteáveis Razor são incompatíveis com o uso de seletores CSS.

Recursos adicionais Blazor WebAssembly

A integração de componentes Razor em páginas Razor ou aplicativos MVC em uma solução hospedada Blazor WebAssembly é suportada no ASP.NET Core no .NET 5 ou posterior. Selecione uma versão .NET 5 ou posterior deste artigo.