Blazor - CRUD com ADO.NET em camadas - III


  Hoje vamos iniciar a criação de um projeto em camadas que realizar o CRUD usando como cliente uma aplicação Blazor Server App.

Continuando a segunda parte do artigo vamos agora definir o projeto Blazor Server.

Definindo o projeto Blazor : Configuração e ajustes

O projeto BlzCrud.App representa a camada de apresentação onde vamos definir os componentes Blazor que vão interagir com o cliente e usar os recursos das demais camadas.

Vamos iniciar definindo no arquivo appsettings.json a string de conexão com o banco de dados :

{
"ConnectionStrings": {
   "DefaultConnection": "Data Source=.;Initial Catalog=CadastroDB;IntegratedSecurity=True"
},
"Logging": {
  
"LogLevel": {
     
"Default": "Information",
         
"Microsoft.AspNetCore": "Warning"
    }
  },
"AllowedHosts": "*"
}

A seguir vamos registrar os serviços na classe Program:

using BlzCrud.Application.Services;
using BlzCrud.Domain.Interfaces;
using BlzCrud.Infra.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

builder.Services.AddScoped<IClienteService, ClienteService>();
builder.Services.AddSingleton<IDataService, DataService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();

Agora vamos incluir no arquivo _Imports.razor os usings que iremos usar no projeto Blazor:

@using System.Net.Http
@
using Microsoft.AspNetCore.Authorization
@
using Microsoft.AspNetCore.Components.Authorization
@
using Microsoft.AspNetCore.Components.Forms
@
using Microsoft.AspNetCore.Components.Routing
@
using Microsoft.AspNetCore.Components.Web
@
using Microsoft.AspNetCore.Components.Web.Virtualization
@
using Microsoft.JSInterop
@
using BlzCrud.App
@
using BlzCrud.App.Shared
@
using BlzCrud.Application.Services
@
using BlzCrud.Domain.Interfaces
@
using BlzCrud.Domain.Entities
 

Na pasta wwwroot do projeto vamos criar a pasta images e incluir nesta pasta a imagem clientes.jpg que iremos usar na página Index.razor.

A seguir vamos ajustar o arquivo NavMenu.razor da pasta Shared com o código a seguir:

...

<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
   <
nav class="flex-column">
      <
div class="nav-item px-3">
          <
NavLink class="nav-link" href="" Match="NavLinkMatch.All">
            <
span class="oi oi-home" aria-hidden="true"></span> Home
          </
NavLink>
      </
div>
      <
div class="nav-item px-3">
           <
NavLink class="nav-link" href="clientes">
              <
span class="oi oi-plus" aria-hidden="true"></span> Clientes
           </
NavLink>
      </
div>
    </
nav>
</
div>
,,,

Vamos alterar o código do componente Index.razor da pasta Pages conforme abaixo:

@page "/"

<PageTitle>Index</PageTitle>

<img src="/images/clientes.jpg" />
 

Criando os componentes Blazor

A seguir vamos criar na pasta Pages os componentes Blazor que vão permitir ao usuário realizar as operações CRUD.

1- Componente Clientes.razor : Exibe a relação dos clientes

@page "/clientes"
@inject IDataService clienteService
<NavLink class="nav-link" href="AddCliente">
    <span class="oi oi-plus" aria-hidden="true"></span> Novo Cliente
</NavLink>
<h1>Cientes</h1>
@if (clientes == null)
{
    <p><em>Carregando...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Nome</th>
                <th>Email</th>
                <th>Telefone</th>
                <th>Ação</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var cliente in clientes)
            {
                <tr>
                    <td>@cliente.ClienteId</td>
                    <td>@cliente.Nome</td>
                    <td>@cliente.Email</td>
                    <td>@cliente.Telefone</td>
                    <td>
                        <a class="nav-link" href="EditCliente/@cliente.ClienteId">
                            <span class="oi oi-pencil" aria-hidden="true"></span> Editar
                        </a>
                        <a class="nav-link" href="DeleteCliente/@cliente.ClienteId">
                            <span class="oi oi-trash" aria-hidden="true"></span> Deletar
                        </a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
}
@code {
    List<Cliente>? clientes;
    protected override async Task OnInitializedAsync()
    {
        clientes  = await Task.Run(() => clienteService.GetClientes());
    }
}

2- Componente AddCliente.razor : Inclui um novo cliente

@page "/addCliente"
@inject IDataService clienteService
@inject NavigationManager NavigationManager
<h2>Criar Cliente</h2>
<hr />
<form>
    <div class="row">
        <div class="col-md-8">
            <div class="form-group">
                <label for="Nome" class="control-label">Nome</label>
                <input for="Nome" class="form-control" @bind="@cliente.Nome" />
            </div>
            <div class="form-group">
                <label for="Email" class="control-label">Email</label>
                <input for="Email" class="form-control" @bind="@cliente.Email" />
            </div>
            <div class="form-group">
                <label for="Nascimento" class="control-label">Nascimento</label>
                <input for="Nascimento" class="form-control" @bind="@cliente.Nascimento" />
            </div>
            <div class="form-group">
                <label for="Telefone" class="control-label">Telefone</label>
                <input for="Telefone" class="form-control" @bind="@cliente.Telefone" />
            </div>
            <div class="form-group">
                <label asp-for="Sexo" class="control-label"></label>
                <select @bind="@cliente.Sexo" class="form-control">
                    <option value="">-- Selecione --</option>
                    <option value="Masculino">Masculino</option>
                    <option value="Feminino">Feminino</option>
                </select>
            </div>
            <div class="form-group">
                <label for="Renda" class="control-label">Renda</label>
                <input for="Renda" class="form-control" @bind="@cliente.Renda" />
            </div>
        </div>
    </div>
    <br />
    <div class="row">
        <div class="col-md-4">
            <div class="form-group">
                <input type="button" class="btn btn-primary" @onclick="@CreateCliente" value="Salvar" />
                <input type="button" class="btn btn-warning" @onclick="@Cancela" value="Cancelar" />
            </div>
        </div>
    </div>
</form>
@code {
    Cliente cliente = new Cliente();
    protected void CreateCliente()
    {
        clienteService.AddCliente(cliente);
        NavigationManager.NavigateTo("Clientes");
    }
    void Cancela()
    {
        NavigationManager.NavigateTo("Clientes");
    }
}  

3- Componente EditCliente.razor : Edita os dados de um cliente

@page "/editCliente/{clienteId}"
@inject IDataService clienteService
@inject NavigationManager NavigationManager
<h2>Editar Cliente</h2>
<hr />
<form>
    <div class="row">
        <div class="col-md-8">
            <div class="form-group">
                <input for="Name" class="form-control" @bind="@cliente.ClienteId" />
            </div>
            <div class="form-group">
                <label for="Nome" class="control-label">Nome</label>
                <input for="Nome" class="form-control" @bind="@cliente.Nome" />
            </div>
            <div class="form-group">
                <label for="Email" class="control-label">Email</label>
                <input for="Email" class="form-control" @bind="@cliente.Email" />
            </div>
            <div class="form-group">
                <label for="Nascimento" class="control-label">Nascimento</label>
                <input for="Nascimento" class="form-control" @bind="@cliente.Nascimento" />
            </div>
            <div class="form-group">
                <label for="Telefone" class="control-label">Telefone</label>
                <input for="Telefone" class="form-control" @bind="@cliente.Telefone" />
            </div>
            <div class="form-group">
                <label asp-for="Sexo" class="control-label"></label>
                <select @bind="@cliente.Sexo" class="form-control">
                    <option value="">-- Selecione --</option>
                    <option value="Masculino">Masculino</option>
                    <option value="Feminino">Feminino</option>
                </select>
            </div>
            <div class="form-group">
                <label for="Renda" class="control-label">Renda</label>
                <input for="Renda" class="form-control" @bind="@cliente.Renda" />
            </div>
        </div>
    </div>
    <br />
    <div class="row">
        <div class="col-md-4">
            <div class="form-group">
                <input type="button" @onclick="@UpdateCliente" class="btn btn-primary" value="Salvar" />
                <input type="button" @onclick="@Cancelar" class="btn btn-warning" value="Cancelar" />
            </div>
        </div>
    </div>
</form>
@code{
    [Parameter]
    public string clienteId { get; set; }
    Cliente cliente = new Cliente();
    protected override async Task OnInitializedAsync()
    {
        cliente =  await Task.Run(()=> clienteService.GetCliente(Convert.ToInt32(clienteId)));
    }
    protected void UpdateCliente()
    {
        clienteService.UpdateCliente(cliente);
        NavigationManager.NavigateTo("Clientes");
    }
    void Cancelar()
    {
        NavigationManager.NavigateTo("Clientes");
    }
}

4- Componente DeleteCliente.razor : Deleta um cliente

@page "/deletecliente/{clienteId}"
@inject IDataService clienteService
@inject NavigationManager NavigationManager
<h3>Deseja deletar este cliente?</h3>
<hr />
<div class="row">
    <div class="col-md-8">
        <div class="form-group">
            <label>Id:</label>
            <label>@cliente.ClienteId</label>
        </div>
        <div class="form-group">
            <label>Nome:</label>
            <label>@cliente.Nome</label>
        </div>
        <div class="form-group">
            <label>Sexo:</label>
            <label>@cliente.Sexo</label>
        </div>
        <div class="form-group">
            <label>Email:</label>
            <label>@cliente.Email</label>
        </div>
        <div class="form-group">
            <label>Telefone:</label>
            <label>@cliente.Telefone</label>
        </div>
    </div>
</div>
<hr />
<div class="row">
    <div class="col-md-4">
        <div class="form-group">
            <input type="button" @onclick="@DeletarCliente" class="btn btn-danger" value="Deletar" />
            <input type="button" @onclick="@Cancelar" class="btn btn-warning" value="Cancelar" />
        </div>
    </div>
</div>
@code {
    [Parameter]
    public string? clienteId { get; set; }
    Cliente cliente = new Cliente();
    protected override async Task OnInitializedAsync()
    {
        cliente = await Task.Run(()=> clienteService.GetCliente(Convert.ToInt32(clienteId)));
    }
    protected void DeletarCliente()
    {
        clienteService.DeleteCliente(Convert.ToInt32(clienteId));
        NavigationManager.NavigateTo("Clientes");
    }
    void Cancelar()
    {
        NavigationManager.NavigateTo("Clientes");
    }
}  

Agora é só alegria...

Executando o projeto teremos o seguinte resultado:

Embora seja um projeto bem simples, você pode melhorá-lo em diversos aspectos como implementar o serviço assíncrono e remover a utilização dos Task.Run usada nos componentes Blazor pois isso não é recomendado. (Programação assíncrona com ADO.NET)

Assim fique a vontade e divirta-se...

Pegue o projeto aqui :   BlzCrud_Adonet.zip  (sem as referências)

"No último dia, o mais importante da festa, Jesus se levantou e disse em alta voz: “Quem tem sede, venha a mim e beba!"
João 7:27

Referências:


José Carlos Macoratti