Introdução ao Blazor: Arquitetura e Desenvolvimento de Componentes SPA com C#

O avanço na capacidade de processamento dos navegadores modernos, consolidado pela implementação padrão do WebAssembly, viabilizou a execução direta de binários compilados no ambiente do cliente. Essa evolução eliminou a dependência exclusiva de JavaScript para manipulação complexa da árvore DOM. Diante desse cenário, a Microsoft apresentou o Blazor, um framework unificado que permite a construção completa de interfaces web utilizando C#, HTML e CSS. Com a compilação para WebAssembly, é possível compartilhar camadas de domínio e regras de negócio entre o servidor e o navegador sem a necessidade de desenvolver código lado cliente em outra linguagem.

Estrutura de Projetos e Ambiente de Execução

O ecossistema Blazor integra-se nativamente ao SDK do .NET Core. A geração inicial de projetos pode ser realizada via interface gráfica ou através da interface de linha de comando utilizando o modelo oficial. Ao analisar a esturtura gerada por padrão, observa-se:

  • wwwroot: Diretório estático dedicado a ativos front-end, como folhas de estilo, scripts e recursos de mídia.
  • Pasta Shared: Contém componentes de layout reutilizáveis, modelos de navegação e arquivos de configuração global de renderização.
  • _Imports.razor: Arquivo de escopo que define namespaces importados automaticamente em todos os componentes Razor do projeto, simplificando declarações explícitas.
  • Program.cs: Ponto de entrada responsável pela configuração do host da aplicação, incluindo registro de serviços e definição do ambiente de execução.
  • Startup.cs: Classe dedicada à configuração de middlewares, roteamento e container de Injeção de Dependência (DI).

Anatomia do Componente Razor

Componentes são as unidades fundamentais de interface no Blazor, identificados pela extensão .razor. Eles combinam marcação declarativa com lógica procedural escrita em C#. Para estruturar um componente funcional, é necessário observar a ordem correta das diretivas e blocos de código:

<h3>Gestão de Ativos</h3>

<div class="input-group mb-3">
    <input type="text" class="form-control" @bind="@novoItem" @bind:event="oninput" placeholder="Identificação do item..." />
    <button class="btn btn-primary" type="button" @onclick="AdicionarNovo">Registrar</button>
</div>

<table class="table table-striped">
    <thead>
        <tr>
            <th>Status</th>
            <th>Descrição</th>
            <th>Ações</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var registro in listaItens)
        {
            <tr>
                <td>@(registro.Pendencia ? "Pendente" : "Concluído")</td>
                <td>@registro.Detalhes</td>
                <td>
                    <button class="btn btn-danger btn-sm" type="button" @onclick="(() => ExcluirItem(registro.Codigo))">
                        Remover
                    </button>
                </td>
            </tr>
        }
    </tbody>
</table>

A diretriz @page, posicionada no cabeçalho do arquivo, registra uma rota específica para o componente, permitindo navegação direta via URL do navegador. A sintaxe aceita caminhos relativos ou absolutos, facilitando o mapeamento de rotas dentro da hierarquia da aplicação.

Para incorporar serviços externos ou repositórios de dados, utiliza-se a diretiva @inject. Ela associa automaticamente uma instância registrada no container DI ao contexto atual do componente, conforme ilustrado abaixo:

@inject ServicoDeRegistros RepositorioDeDados

Diferente das abordagens tradicionais baseadas em controladores MVC, o Blazor encapsula a lógica de ciclo de vida dentro do próprio componente. Métodos assíncronos como OnInitializedAsync são acionados pelo motor de renderização assim que a instância é carregada na memória do cliente, sendo ideais para operações de busca ou inicialização de estado:

@code {
    private List<itemcontrole> listaItens = new();
    private string novoItem;

    protected override async Task OnInitializedAsync()
    {
        var dadosExistentes = await RepositorioDeDados.ConsultarTodosAsync();
        listaItens.Clear();
        listaItens.AddRange(dadosExistentes);
    }

    private void AdicionarNovo()
    {
        if (string.IsNullOrWhiteSpace(novoItem)) return;

        listaItens.Add(new ItemControle 
        { 
            Codigo = Guid.NewGuid().ToString(), 
            Detalhes = novoItem, 
            Pendencia = true 
        });
        
        novoItem = string.Empty;
    }

    private void ExcluirItem(string id)
    {
        var alvo = listaItens.FirstOrDefault(x => x.Codigo == id);
        if (alvo != null)
        {
            listaItens.Remove(alvo);
        }
    }
}</itemcontrole>

O bloco @code centraliza campos privados, manipuladores de eventos e métodos de ciclo de vida. A vinculação bidirecional de formulários é tratada pela diretiva @bind, sincronizando automaticamente o valor do controle HTML com a variável C# correspondente. Eventos de interação, como cliques, são atribuídos diretamente a delegados ou expressões lambda via @onclick, garantindo que toda a manipulação do DOM ocorra via camada C#.

A execução ocorre inteiramente no navegador após a compilação do código gerenciado para WASM. A comunicação com APIs REST, banco de dados ou serviços nativos é feita internamente através de mecanismos de interop com JavaScript quando necessário, mantendo a abstração do desenvolvedor isolada das particularidades do ambiente browser. Essa arquitetura uni-fiel reduz drasticamente a sobrecarga de manutenção entre diferentes camadas da aplicação.

Tags: Blazor ASP.NET Core WebAssembly C# Razor Components

Publicado em 8-29 01:53