Hoje criaremos uma aplicação ASP.NET Core usando o Blazor e o Visual Studio 2017 e faremos um CRUD básico usando os recursos do Entity Framework Core.
Os pré-requisitos, são:
- Instalar o .NET Core 2.1 SDK
- Instalar a última versão do Visual Studio 2017 (15.7)
- Instalar a ASP .NET Core Blazor Language Services extension.
- SQL Server 2012 ou superior
Nota: O Blazor não é suportado em versões do Visual Studio anteriores a versão v15.7 e precisa do .NET Core SDK 2.1
Como exemplo eu vou usar um banco de dados já criado no SQL Server com o nome de Cadastro e a tabela Clientes, que possui a seguinte estrutura e dados:
O Script SQL para gerar a tabela Clientes segue abaixo:
USE [Cadastro] GO CREATE TABLE [dbo].[Clientes]( [ClienteId] [int] IDENTITY(1,1) NOT NULL, [Nome] [nvarchar](80) NOT NULL, [Email] [nvarchar](150) NULL, [Pais] [nvarchar](20) NULL )
Agora mãos à obra!
Criando o projeto ASP .NET Core Blazor no VS 2017
Após esse procedimento, abra o VS 2017 Community e selecione “File” > “New Project“;
Em seguida, selecione .NET Core e o template ASP .NET Core Web Application, informe o nome Blazor_Crud e clique em “OK“;
Na próxima janela, selecione o template Blazor (ASP .NET Core hosted) e clique em “OK“:
Na janela Solution Explorer podemos ver a estrutura do projeto criado conforme mostra a imagem a seguir:
Observe que temos três projetos criados nesta solução:
- BlazorCrud.Client: possui o código do lado do cliente e contém as páginas que serão renderizadas no navegador.
- BlazorCrud.Server: possui o código do lado do servidor, tal como as operações relacionados com o banco de dados e nossa Web API.
- BlazorCrud.Shared: possui o código compartilhado que pode ser acessado tanto pelo cliente como pelo servidor.
Executando o projeto iremos obter no navegador o seguinte resultado (que já analisamos neste artigo):
Vemos que nosso projeto esta funcional e apresenta o resultado padrão.
Essas páginas que foram criadas por padrão não afetarão o nosso aplicativo, mas vamos excluir as páginas Fetchdata e Counter da pasta BlazorCrud.Client /Pages.
Adicionando o modelo de domínio na Aplicação
Clique com o botão direito do mouse sobre o projeto Blazor_Crud.Shared, selecione “Add” > “New Folder” e informe o nome Models.
A seguir crie uma classe chamada Cliente na pasta Models com o código abaixo:
Essa classe contém as propriedades do modelo Cliente, que será mapeado para a tabela Clientes.
Observe que estamos usando o atributo [Required] da DataAnnotations. Para isso temos que incluir uma referência ao pacote no projeto via Nuget:
Vamos agora criar nossa camada de acesso à dados.
Criando a camada de acesso à dados da aplicação Blazor
Clique com o botão direito do mouse sobre o projeto Blazor_Crud.Server e a seguir selecione “Add” > “New Folder” e informe o nome DataAccess.
A seguir, inclua nesta pasta a classe AppDbContext, que é a nossa classe de contexto que vai herdar da classe DbContext do Entity Framework Core e inclua o código abaixo nesta classe:
using Blazor_Crud.Shared.Models; using Microsoft.EntityFrameworkCore; namespace Blazor_Crud.Server.DataAccess { public class AppDbContext : DbContext { public virtual DbSet<Cliente> Clientes { get; set; } public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } } }
Nesta classe usamos uma referência ao Entity Framework Core para poder herdar da classe DbContext e definir assim a propriedade DbSet<Cliente> que mapeia para a tabela Clientes.
Precisamos agora registrar o contexto como um serviço e definir o provedor do banco de dados e a string de conexão. Fazemos isso no arquivo Startup do projeto.
Abra o arquivo Startup.cs e inclua o código destacado em azul abaixo:
public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } public void ConfigureServices(IServiceCollection services) { services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddMvc(); services.AddResponseCompression(options => { options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { MediaTypeNames.Application.Octet, WasmMediaTypeNames.Application.Wasm, }); }); } .... }
Tivemos que criar a propriedade Configuration para poder acessar a string de conexão que foi definida no arquivo appsettings.json. Como esse arquivo não existe por padrão, tivemos também que incluir o arquivo no projeto.
{ "ConnectionStrings": { "DefaultConnection": "Data Source=Macoratti;Initial Catalog=Cadastro;Integrated Security=True" } }
Neste arquivo definimos a string de conexão local do meu SQL Server (use a string de conexão do seu ambiente).
Agora vamos criar a nossa Web API que expõe os serviços para realizar o CRUD usando o EF Core.
Criando a WEB API – Incluindo o Controller ClientesController
Clique com o botão direito sobre a pasta Blazor_Crud.Server/Controllers e selecione “Add” > “Controller“.
A seguir selecione o template API Controller with actions, using Entity Framework e clique em “Add“;
A seguir informe o modelo – Cliente – e o contexto conforme abaixo e clique em “Add“;
Note que não estamos gerando as views. Vamos fazer isso na segunda parte do artigo.
Inclua o código abaixo no controlador gerado:
using Blazor_Crud.Server.DataAccess; using Blazor_Crud.Shared.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Blazor_Crud.Server.Controllers { [Produces("application/json")] [Route("api/[controller]")] [ApiController] public class ClientesController : Controller { private readonly AppDbContext _context; public ClientesController(AppDbContext context) { _context = context; } // GET: api/Clientes [HttpGet] public IEnumerable<Cliente> GetClientes() { return _context.Clientes; } // GET: api/Clientes/5 [HttpGet("{id}")] public async Task<IActionResult> GetCliente([FromRoute] int id) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var cliente = await _context.Clientes.FindAsync(id); if (cliente == null) { return NotFound(); } return Ok(cliente); } // PUT: api/Clientes/5 [HttpPut("{id}")] public async Task<IActionResult> PutCliente([FromRoute] int id, [FromBody] Cliente cliente) { if (!ModelState.IsValid) { return BadRequest(ModelState); } if (id != cliente.ClienteId) { return BadRequest(); } _context.Entry(cliente).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!ClienteExists(id)) { return NotFound(); } else { throw; } } return NoContent(); } // POST: api/Clientes [HttpPost] public async Task<IActionResult> PostCliente([FromBody] Cliente cliente) { if (!ModelState.IsValid) { return BadRequest(ModelState); } _context.Clientes.Add(cliente); await _context.SaveChangesAsync(); return CreatedAtAction("GetCliente", new { id = cliente.ClienteId }, cliente); } // DELETE: api/Clientes/5 [HttpDelete("{id}")] public async Task<IActionResult> DeleteCliente([FromRoute] int id) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var cliente = await _context.Clientes.FindAsync(id); if (cliente == null) { return NotFound(); } _context.Clientes.Remove(cliente); await _context.SaveChangesAsync(); return Ok(cliente); } private bool ClienteExists(int id) { return _context.Clientes.Any(e => e.ClienteId == id); } } }
Neste momento a estrutura da nossa solução pode ser vista a seguir:
A lógica do nosso backend está pronta. Vamos agora definir o código do lado do cliente.
Na próxima parte do artigo vamos definir o código do projeto Blazor_Crud.Client.