Overview
O que é Blazor?
É um framework para aplicações “client-side” escrito em .NET e rodando em cima do WebAssembly.
É baseado em tecnologias já existentes como HTLM e CSS, mas você pode usar C# e Razor ao invés de Javascript para buildar os componentes. Oferece todos os benefícios de uma plataforma de aplicativo de página única (SPA) rica e moderna ao usar o .NET de ponta a ponta.
A ideia sobre o Blazor é ser capaz de combinar Razor e C # em um projeto da web do lado do cliente que roda completamente no navegador.
WebAssembly
WebAssembly é um formato binário para o código no navegador e é executado muito mais rápido do que o JavaScript tradicional. Oferece ao navegador várias vantagens, como:
- Executa em desempenho quase nativo
- É executado em uma caixa de areia segura para a memória
- Compila a partir de uma variedade de linguagens, ou seja, .NET, C, C ++, Java, Rust, etc.
A principal vantagem do WebAssembly é que ele lida muito bem com trabalhos com muita memória e multithreading, em comparação com o javascript.
Features
O Blazor contém todos os recursos de uma estrutura web moderna, como:
- Um modelo de componente para a construção de IU combinável
- Roteamento
- Layouts
- Formulários e validação
- Injeção de dependência
- Recarregamento ao vivo no navegador durante o desenvolvimento
- Renderização do lado do servidor
- Depuração completa do .NET em navegadores e no IDE
- Rich IntelliSense e ferramentas
- Publicação e corte de tamanho de aplicativo
Setup
- Baixe e instale o .NET Core 2.1 SDK (2.1.300 ou posterior).
- Baixe e instale o Visual Studio 2017 (15.7 ou posterior) com o ASP.NET e a carga de trabalho de desenvolvimento da web selecionados.
Fonte: link
Um CRUD simples utilizando Blazor, EFCore e InMemoryDatabase
Neste exemplo vou lhes mostrar como fazer um simples CRUD utilizando as seguintes ferramentas:
Após a instalação do Blazor, vamos criar um projeto através do seguinte comando:
dotnet new blazorserver -o <VOCE_ESCOLHE_O_NOME> --no-https
cd NOME_QUE_VOCE_ESCOLHEU
Observação: você pode utilizar o Visual Studio e criar o projeto através do caminho “File > New Solution” e pesquisar por “Blazor”
Para saber se está tudo OK, basta digitar o comando
dotnet run
Por padrão, já vem criada uma aplicação para você se ambientar com o Blazor. Para visualizar a aplicação, acesse http://localhost:5000
Agora, vamos criar as nossas classes, páginas e instalar alguns pacotes necessários para fazermos o CRUD.
Setup:
Primeiro, vamos instalar o pacote Microsoft.EntityFrameworkCore.InMemory. Para isso, digite o seguinte comando (dentro da pasta do seu projeto):
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 3.1.8
Codificando
Agora, dentro da pasta “Data”, vamos criar as seguintes classes: “Context.cs” e “ClienteService.cs”.
A classe “ClienteService.cs” terá o seguinte código:
using Blazor.Client.Data; | |
using Blazor.Client.Models; | |
using System.Collections.Generic; | |
using System.Threading.Tasks; | |
namespace Blazor.Data | |
{ | |
public class ClienteService | |
{ | |
readonly Context _context = new Context(); | |
/// <summary> | |
/// Add cliente to the memory database | |
/// </summary> | |
/// <param name="cliente">The Cliente object</param> | |
public async Task AddAsync(Cliente cliente) | |
{ | |
await Task.Run(() => _context.Clientes.Add(cliente)); | |
SaveChanges(); | |
} | |
/// <summary> | |
/// Add cliente to the memory database | |
/// </summary> | |
/// <param name="cliente">The Cliente object</param> | |
public void Add(Cliente cliente) | |
{ | |
_context.Clientes.Add(cliente); | |
SaveChanges(); | |
} | |
/// <summary> | |
/// Get all Clientes from memory database | |
/// </summary> | |
/// <returns>A list of all Clientes</returns> | |
public async Task<IEnumerable<Cliente>> GetAllAsync() | |
{ | |
List<Cliente> retorno; | |
return await Task.Run(() => retorno = new List<Cliente>(_context.Clientes)); | |
} | |
/// <summary> | |
/// Get all Clientes from memory database | |
/// </summary> | |
/// <returns>A list of all Clientes</returns> | |
public IEnumerable<Cliente> GetAll() | |
{ | |
List<Cliente> retorno = new List<Cliente>(_context.Clientes); | |
return retorno; | |
} | |
/// <summary> | |
/// Get the Cliente by its ID | |
/// </summary> | |
/// <param name="id">An integer ID</param> | |
/// <returns></returns> | |
public Cliente GetById(int id) | |
{ | |
var query = _context.Clientes.Find(id); | |
return query; | |
} | |
/// <summary> | |
/// Get the Cliente by its ID | |
/// </summary> | |
/// <param name="id">An integer ID</param> | |
/// <returns></returns> | |
public async Task<Cliente> GetByIdAsync(int id) | |
{ | |
Cliente cliente; | |
return await Task.Run(() => cliente = _context.Clientes.Find(id)); | |
} | |
/// <summary> | |
/// Update the Cliente on memory database | |
/// </summary> | |
/// <param name="cliente">The Cliente object</param> | |
public void Update(Cliente cliente) | |
{ | |
_context.Clientes.Update(cliente); | |
SaveChanges(); | |
} | |
/// <summary> | |
/// Update the Cliente on memory database | |
/// </summary> | |
/// <param name="cliente">The Cliente object</param> | |
public async Task UpdateAsync(Cliente cliente) | |
{ | |
await Task.Run(() => _context.Clientes.Update(cliente)); | |
SaveChanges(); | |
} | |
/// <summary> | |
/// Delete the Client on memory database | |
/// </summary> | |
/// <param name="cliente">The Cliente object</param> | |
public void Delete(Cliente cliente) | |
{ | |
_context.Clientes.Remove(cliente); | |
SaveChanges(); | |
} | |
/// <summary> | |
/// Delete the Client on memory database | |
/// </summary> | |
/// <param name="cliente">The Cliente object</param> | |
public async Task DeleteAsync(Cliente cliente) | |
{ | |
await Task.Run(() => _context.Clientes.Remove(cliente)); | |
SaveChanges(); | |
} | |
private int SaveChanges() | |
{ | |
return _context.SaveChanges(); | |
} | |
} | |
} |
A classe “Context.cs” terá o seguinte código:
using Blazor.Client.Models; | |
using Microsoft.EntityFrameworkCore; | |
namespace Blazor.Client.Data | |
{ | |
public class Context : DbContext | |
{ | |
public DbSet<Cliente> Clientes { get; set; } | |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) | |
{ | |
base.OnConfiguring(optionsBuilder); | |
optionsBuilder.UseInMemoryDatabase("BlazorDB"); | |
} | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
modelBuilder.Entity<Cliente>() | |
.HasKey(c => c.Id); | |
} | |
} | |
} |
Agora, dentro da pasta “Models”, vamos criar a seguinte classe:
A classe “Model.cs” terá o seguinte código:
using System; | |
using System.ComponentModel; | |
using System.ComponentModel.DataAnnotations; | |
using System.ComponentModel.DataAnnotations.Schema; | |
namespace Blazor.Client.Models | |
{ | |
public class Cliente | |
{ | |
[Key] | |
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] | |
public int Id { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o nome!")] | |
[StringLength(60, MinimumLength = 4, | |
ErrorMessage = "O nome deve ter no minimo 4 e no maximo 60 caracteres!")] | |
[DisplayName("Nome")] | |
public string Nome { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o RG!")] | |
[StringLength(9)] | |
[DisplayName("RG")] | |
public string Rg { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o CPF!")] | |
[StringLength(11, ErrorMessage = "O CPF deve conter 11 digitos")] | |
[DisplayName("CPF")] | |
public string Cpf { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o Endereco!")] | |
[StringLength(60)] | |
[DisplayName("Endereco")] | |
public string Endereco { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o Telefone!")] | |
[StringLength(11)] | |
[DisplayName("Telefone")] | |
public string Telefone { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o Celular!")] | |
[StringLength(12)] | |
[DisplayName("Celular")] | |
public string Celular { get; set; } | |
[Required(ErrorMessage = "Por favor, preencha o email!")] | |
[EmailAddress(ErrorMessage = "Email invalido!")] | |
[StringLength(60)] | |
[DisplayName("Email")] | |
public string Email { get; set; } | |
} | |
} |
Agora, dentro da pasta “Pages”, vamos criar a pasta “Clientes” e dentro dela as seguintes páginas: “Cadastrar.razor” e “Editar.razor”.
Ainda na pasta “Pages”, vamos criar a página “Cliente.razor”.
A página “Cadastrar.razor” terá o seguinte código:
@page "/Clientes/cadastrar" | |
@using Blazor.Data | |
@using Models = Blazor.Client.Models | |
@inject ClienteService Service | |
@inject IJSRuntime JSRuntime | |
@inject NavigationManager NavigationManager | |
<h3>Cadastrar Clientes</h3> | |
<div class="container"> | |
<h1 class="text-center">Cadastro de Clientes</h1> | |
<div class="row" style="padding-top: 10%"> | |
<div class="col-lg-12"> | |
<div class="form-group-lg"> | |
<EditForm class="text-center" Model="@_cliente"> | |
<DataAnnotationsValidator /> | |
<ValidationSummary /> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Nome"> Nome:</label> | |
<InputText id="Nome" @bind-Value="@_cliente.Nome" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<label id="Rg">RG:</label> | |
<InputText id="Rg" @bind-Value="@_cliente.Rg" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Cpf">CPF:</label> | |
<InputText id="Cpf" @bind-Value="@_cliente.Cpf" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<label id="Endereco">Endereço:</label> | |
<InputText id="Endereco" @bind-Value="@_cliente.Endereco" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Telefone">Telefone:</label> | |
<InputText id="Telefone" @bind-Value="@_cliente.Telefone" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<label id="Celular">Celular:</label> | |
<InputText id="Celular" @bind-Value="@_cliente.Celular" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Email">E-mail:</label> | |
<InputText id="Email" @bind-Value="@_cliente.Email" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<br /> | |
<br /> | |
<input type="submit" value="Cadastrar" class="btn btn-primary" @onclick="OpenModal" /> | |
</div> | |
</div> | |
</EditForm> | |
</div> | |
</div> | |
</div> | |
</div> | |
@code { | |
private Models.Cliente _cliente = new Models.Cliente(); | |
private int idCount = 0; | |
/// <summary> | |
/// It opens the JS alert with a message | |
/// </summary> | |
/// <returns>void</returns> | |
public async Task OpenModal() | |
{ | |
await JSRuntime.InvokeAsync<string>( | |
"jsFunctions.openModalCadastro", null); | |
AddCliente(); | |
} | |
private void AddCliente() | |
{ | |
_cliente.Id = idCount++; | |
Service.Add(_cliente); | |
NavigationManager.NavigateTo("cliente"); | |
} | |
} |
E a página “Editar.razor” terá o seguinte código:
@page "/Clientes/editar/{Id:int}" | |
@using Blazor.Data | |
@using Models = Blazor.Client.Models | |
@inject ClienteService Service | |
@inject IJSRuntime JSRuntime | |
@inject NavigationManager NavigationManager | |
<h3>Cadastrar Clientes</h3> | |
<div class="container"> | |
<h1 class="text-center">Cadastro de Clientes</h1> | |
<div class="row" style="padding-top: 10%"> | |
<div class="col-lg-12"> | |
<div class="form-group-lg"> | |
<EditForm class="text-center" Model="@_cliente"> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Nome"> Nome:</label> | |
<InputText id="Nome" @bind-Value="@_cliente.Nome" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<label id="Rg">RG:</label> | |
<InputText id="Rg" @bind-Value="@_cliente.Rg" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Cpf">CPF:</label> | |
<InputText id="Cpf" @bind-Value="@_cliente.Cpf" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<label id="Endereco">Endereço:</label> | |
<InputText id="Endereco" @bind-Value="@_cliente.Endereco" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Telefone">Telefone:</label> | |
<InputText id="Telefone" @bind-Value="@_cliente.Telefone" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<label id="Celular">Celular:</label> | |
<InputText id="Celular" @bind-Value="@_cliente.Celular" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-lg-6"> | |
<label id="Email">E-mail:</label> | |
<InputText id="Email" @bind-Value="@_cliente.Email" class="form-control" /> | |
<span class="text-danger" style="font-size:small;"></span> | |
</div> | |
<div class="col-lg-6"> | |
<br /> | |
<br /> | |
<input type="submit" value="Editar" class="btn btn-primary" @onclick="OpenModal" /> | |
</div> | |
</div> | |
</EditForm> | |
</div> | |
</div> | |
</div> | |
</div> | |
@code { | |
private Models.Cliente _cliente; | |
[Parameter] | |
public int Id { get; set; } | |
protected override async Task OnInitializedAsync() | |
{ | |
_cliente = Service.GetById(Id); | |
} | |
public async Task OpenModal() | |
{ | |
await JSRuntime.InvokeAsync<string>( | |
"jsFunctions.openModalEdit", null); | |
EditarCliente(); | |
} | |
private void EditarCliente() | |
{ | |
Service.Update(_cliente); | |
NavigationManager.NavigateTo("cliente"); | |
} | |
} |
Repare que em ambas as páginas temos códigos C# escritos dentro do bloco “@code”. Dentro desse bloco é possível criar qualquer código em C#.
Testando
Após realizar a codificação, rode o comando “dotnet build” para buildar a aplicação. Caso apareça algum erro, leia-o atentamente e verifique os passos anteriores deste artigo.
Deu tudo certo? Então, vamos rodar nossa aplicação:
dotnet run
Essa é a nossa página inicial:
Você pode navegar pelas páginas através do menu no lado esquerdo.
Nossa págna “Cliente” está vazia:
Vamos cadastrar alguns clientes:
Agora, nossa página de “Clientes” foi preenchida:
Repare que podemos editar e excluir o dado cadastrado.
Vamos, primeiro, editar:
We made it!
Todas as funções desse CRUD estão na classe “ClienteService.cs”. Lembra do bloco “@code” dentro das páginas “.razor”? Pois bem, é nesse bloco que chamamos as funções da nossa classe.
Este foi um pequeno exemplo de como utilizar o C# com WebAssembly através do Blazor. Espero que tenham gostado.
Qualquer dúvida, crítica ou sugestão deixe nos comentários.
Còdigo no Github: source code
Um grande abraço!
Top comments (0)