ASP .NET Core - CRUD usando React.js e Entity Framework Core - I


 Hoje vamos criar uma aplicação ASP .NET Core com Reacjt.js e realizar um CRUD básico usando o Entity Framework Core.     

O React é uma biblioteca JavaScript declarativa, eficiente e flexível para criar interfaces com o usuário. Ela permite compor interfaces de usuário complexas a partir de pequenas e isolados trechos de códigos chamados “componentes”.

Podemos integrar facilmente o React em aplicações ASP .NET Core usando o template para criação de projetos que usam o React.js.

Nota: Veja uma instrodução bem básica ao React nesta série de artigos: React - Uma introdução bem básica - I

Hoje, vamos criar uma aplicação ASP.NET Core usando o React.js e o Visual Studio 2017 e realizar um CRUD básico usando os recursos do Entity Framework Core.

Os pré-requisitos necessários são:

Como exemplo eu vou usar um banco de dados já criado no SQL Server com o nome de CadastroDB e as tabelas Contatos e Cidades que possuem a seguinte estrutura e dados:

1- Contatos

2- Cidades

Os Scripts SQL para gerar as tabelas Clientes e Cidades seguem abaixo:

CREATE TABLE [dbo].[Contatos](
  ContatoId int IDENTITY(1,1) NOT NULL,
  Nome nvarchar(80) NOT NULL,
  Email nvarchar(100) NOT NULL,
  Cidade nvarchar(50) NOT NULL,
  Sexo nvarchar(20) NOT NULL
)
CREATE TABLE [dbo].[Cidades]
(
  CidadeId int IDENTITY(1,1) NOT NULL,
  CidadeNome nvarchar(100) NOT NULL
)

Agora mãos à obra...

Criando o projeto ASP .NET Core com React no VS 2017

Após esse procedimento abra o VS 2017 Community e selecione File ->New Project;

Selecione .NET Core e o template ASP .NET Core Web Application e informe o nome AspCore_ReactCrud e clique em OK;

Na próxima janela selecione ASP .NET Core 2.0 e o template React.js e clique em OK:

Nota: O template gerado para ASP .NET Core 2.1 é diferente da versão 2.0.

 

Na janela Solution Explorer podemos ver a estrutura do projeto criado conforme mostra a imagem a seguir:

Observe que temos as pastas no projeto criado nesta solução:

  1. ClientApp – Possui o código do lado do cliente e contém as páginas que serão renderizadas no navegador.
     
  2. Controllers – Possui o código do lado do servidor, tal como as operações relacionados com o banco de dados e nossa Web API.
     
  3. Views – Possui as views da aplicação ASP .NET Core. A interface com o usuário será definida na pasta ClientApp/components

 

Executando o projeto iremos obter no navegador o seguinte resultado:

Vemos que nosso projeto esta funcional e apresenta o resultado padrão.

Incluindo a referência para ter acesso ao Migrations do EF Core

Precisamos instalar o pacote Microsoft.EntityFrameworkCore.Tools no projeto para ter acesso aos comandos do Migrations.

Abra uma janela do gerenciador de pacotes Nuget,  NuGet Package Manager -> Package Manager Console,  e digite o comando :

Gerando o modelo de domínio na Aplicação e o contexto a partir do Banco de dados

Vamos gerar as classes do nosso domínio e a classe de contexto usando o Scaffold do Migrations do EF Core.

Antes vamos criar uma pasta Models em nosso projeto para armazenar as classes do modelo de dominio e de contexto.

Para gerar as entidades e o contexto vamos usar o comando Scaffold-DbContext que possui a seguinte sintaxe:

Scaffold-DbContext [-Connection] <String> [-Provider] <String> [-OutputDir <String>] [-ContextDir <String>] [-Context <String>] [-Schemas <String[]>] [-Tables <String[]>] [-DataAnnotations] 
[-UseDatabaseNames] [-Force] [-Project <String>] [-StartupProject <String>] [<CommonParameters>]

Para ver o help do comando digite : get-help Scaffold-DbContext -detailed

Para o nosso exemplo o comando fica assim:

Scaffold-DbContext "Data Source=Macoratti;Initial Catalog=CadastroDB;Integrated Security=True" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables Contatos, Cidades -Context AppDbContext

Neste comando definimos:

- A string de conexão : "Data Source=Macoratti;Initial Catalog=CadastroDB;Integrated Security=True"
- O provedor para o SQL Server : Microsoft.EntityFrameworkCore.SqlServer
- A pasta onde vamos gerar as classes : -OutputDir Models
- O nome das tabelas : -Tables Contatos, Cidades
- A classe de contexto : -Context AppDbContext

Após a conclusão do comando vemos na pasta Models o modelo de domínio e a classe de contexto gerados:

Vamos fazer um pequeno ajuste na classe de contexto gerada.

Abra a classe AppDbContext e no método OnConfiguring() comente o código que define a string de conexão:

Vamos definir a string de conexão e o provedor na classe Startup, registrando o contexto como um serviço para poder usar a injeção de dependência do contâiner nativo da ASP .NET Core. Assim podermos injetar a instãncia do nosso contexto quando formos criar a nossa Web API na pasta Controllers.

Abra o arquivo Startup e no método ConfigureServices defina o código como abaixo:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AppDbContext>(options =>
              options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddMvc();
        }

A seguir inclua no arquivo appsettings.json a string de conexão :

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=Macoratti;Initial Catalog=CadastroDB;Integrated Security=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

Vamos agora criar nossa camada de acesso a dados.

Criando a WEB API - Incluindo o Controller ContatoController

Clique com o botão direito sobre a pasta 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 - Contato -  e o contexto, conforme abaixo e informe o nome ContatoController e clique em Add;

Abaixo temos o código com ajustes da nossa Web API:

using AspCore_ReactCrud.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AspCore_ReactCrud.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class ContatoController : Controller
    {
        private readonly AppDbContext _context;
        public ContatoController(AppDbContext contexto)
        {
            _context = contexto;
        }
        // GET: api/Contato
        [HttpGet]
        public IEnumerable<Contato> GetContatos()
        {
            return _context.Contatos;
        }
        // GET: api/Contato/5
        [HttpGet("{id}")]
        public async Task<IActionResult> GetContato([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var contato = await _context.Contatos.FindAsync(id);
            if (contato == null)
            {
                return NotFound();
            }
            return Ok(contato);
        }
        // PUT: api/Contato/5
        [HttpPut("{id}")]
        public async Task<IActionResult> PutContato([FromRoute] int id, [FromBody] Contato contato)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            if (id != contato.ContatoId)
            {
                return BadRequest();
            }
            _context.Entry(contato).State = EntityState.Modified;
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ContatoExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return NoContent();
        }

        // POST: api/Contato
        [HttpPost]
        public async Task<IActionResult> PostContato([FromBody] Contato contato)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            _context.Contatos.Add(contato);
            await _context.SaveChangesAsync();
            return CreatedAtAction("GetContato", new { id = contato.ContatoId }, contato);
        }

        // DELETE: api/Contato/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteContato([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var contato = await _context.Contatos.FindAsync(id);
            if (contato == null)
            {
                return NotFound();
            }
            _context.Contatos.Remove(contato);
            await _context.SaveChangesAsync();
            return Ok(contato);
        }
        [HttpGet]
        [Route("api/Contato/GetCidades")]
        public IEnumerable<Cidade> Details()
        {
            return _context.Cidades.ToList();
        }
        private bool ContatoExists(int id)
        {
            return _context.Contatos.Any(e => e.ContatoId == id);
        }
    }
}

A lógica do nosso backend esta pronta. Vamos agora definir o código do lado do cliente.

Na próxima parte do artigo vamos criar os componentes React da nossa aplicação.

"Porque o coração deste povo está endurecido,E ouviram de mau grado com seus ouvidos,E fecharam seus olhos;Para que não vejam com os olhos,E ouçam com os ouvidos,e compreendam com o coração,e se convertam,e eu os cure."
Mateus 13:15

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti