Olá pessoal, hoje eu gostaria de mostrar e explicar a geração de Web API do tipo REST usando a ferramenta da Microsoft. Essa geração não é convencional e eu acabo utilizando ela em alguns casos específicos, pois eu preciso de dados retornados de mais de uma tabela ao mesmo tempo com uma relação interessante. Veja o que foi utilizado:
Utilizado:
- Ferramenta: Visual Studio
- Linguagem: C#
- Plataforma: Web Api
- MVC Microsoft
Como todos sabem, o projeto Web API retorna basicamente dados de uma tabela e se você quiser acessar outra correlacionado, é necessário acessar outros métodos passando parâmetros. E como estou acostumado a fazer consultas grandes para buscar dados em várias tabelas, precisei estudar uma maneira onde não encontrei muito na Internet. Naqueles momentos que você tem um “inside”, acabei criando uma nova classe com os dados eu precisava.
Vamos gerar classe de GET e SET comum e que tinham apenas as propriedades do SELECT dentro do método na “Controller”. As propriedades GET e SET estão dentro da Model. Veja a listagem 1.
Listagem 1 - Declarando get e set
public class ContaEValor
{
[Key]
public Int64 IdConta { get; set; }
public String DescricaoConta { get; set; }
public String Tipo { get; set; }
public Double? Valor { get; set; }
}
Lembre-se que o intuito de criar uma classe assim é porque eu não quero ficar fazendo várias consultas no Web API, preciso que apenas com uma consulta retorne pra mim todos os valores que eu preciso. Essa foi uma solução que criei para retornar o que eu quero.
Gerei a controller utilizando os padrões da ferramenta depois de gerar a classe com GET e SET. Clicando com o botão direito do mouse em cima da pasta chamada “Controller”, depois no sub-menu Add e depois “Controller…”. É importante compilar seu projeto todo antes de querer gerar essa controller ok. Veja a figura 1.
Figura 1 - Criando Controller
Depois de clicar no sub-menu “Controller” aparece outra tela para escolher o tipo de Scaffold, um ajudante para gerar classe e métodos utilizando Entity Framework e actions. Note que a opção selecionada na figura 2 é a versão Web API 2. Ao lado direito da imagem, possui uma breve explicação sobre esse tipo de controller. Essa opção criar uma controller com ações REST para criar, ler, atualizar, deletar e listar entidades baseado no contexto do Entity Framework para dados. Veja a figura 2.
Figura 2 - Utilizando Scaffold para gerar métodos
Ao clicar no botão Add no final da figura 2, vai abrir outra tela solicitando informações para gerar métodos e classe baseado no contexto. O nome da controller está baseada na classe model. Veja a figura 3.
Figura 3 - Colocando informações de configuração para gerar a Controller
A ferramenta Visual Studio gera no final uma classe “Controller" com vários métodos prontos e simples como o CRUD. Os métodos foram gerados, veja a lista 1.
Lista 1 - CRUD completo gerado
// GET: api/Contas
public IQueryable
{
return db.Conta;
}
// GET: api/Contas/5
[ResponseType(typeof(Conta))]
public IHttpActionResult GetConta(long id)
{
Conta conta = db.Conta.Find(id);
if (conta == null)
{
return NotFound();
}
return Ok(conta);
}
// PUT: api/Contas/5
[ResponseType(typeof(void))]
public IHttpActionResult PutConta(long id, Conta conta)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != conta.IdConta)
{
return BadRequest();
}
db.Entry(conta).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ContaExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Contas
[ResponseType(typeof(Conta))]
public IHttpActionResult PostConta(Conta conta)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Conta.Add(conta);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = conta.IdConta }, conta);
}
// DELETE: api/Contas/5
[ResponseType(typeof(Conta))]
public IHttpActionResult DeleteConta(long id)
{
Conta conta = db.Conta.Find(id);
if (conta == null)
{
return NotFound();
}
db.Conta.Remove(conta);
db.SaveChanges();
return Ok(conta);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool ContaExists(long id)
{
return db.Conta.Count(e => e.IdConta == id) > 0;
}
Lembre-se que este documento não é focado a usar esse CRUD, vamos criar outro método que busca com mais de uma tabela no usando INNER ou LEFT JOIN. Isso mesmo, buscando mais de uma tabela passando um ID. A listagem 2 mostra um método que retorna o tipo IEnumerable
Listagem 2 - Método com INNER JOIN
[Route("api/ContaEValorsZerada/{id}")]
public IEnumerable
{
StringBuilder str = new StringBuilder();
str.Append(@"
SELECT
Conta.IdConta,
Conta.DescricaoConta,
Dados.Tipo,
Dados.Valor
FROM
Conta
LEFT JOIN Dados ON Dados.IdConta = Conta.IdConta
WHERE Conta.IdUsuario=@idUsuario ");
IDataParameter idUs = new SqlParameter();
idUs.DbType = DbType.Int64;
idUs.ParameterName = "@idUsuario";
idUs.Value = int.Parse(id);
idUs.SourceColumn = "IdUsuario";
var resultado = db.Database.SqlQuery
idUs).AsEnumerable();
if (resultado == null)
return null;
return resultado;
}
O SqlQuery é do Entity Framework criado pela Microsoft e mantido pela comunidade MVP e própria empresa. Com tudo isso, você consegue criar varias classes específicas com GET e SET para trazer apenas os dados que deseja no SELECT qualquer. Você usa o SQL personalizado do seu jeito para o retorno dos dados. Retornando os dados exatos, aqueles que evitam buscar mais de uma vez reduz o REQUEST, reduz o custo do servidor e reduz o tempo que o usuário fica esperando para ver os dados.
Eu já participei de projetos que o desenvolvedor utilizando o padrão Java e precisava fazer uma consulta que não retornava tudo e para buscar tudo precisava fazer dois ou três requisições no Web API / Web Service. O custo aumenta muito no servidor e para a empresa que tem que pagar. Fora que custa mais no consumo do 4G ou 3G do celular do cliente. Fique de olho nisso e se preocupe realmente com esse tipo de coisa.
Espero que tenha gostado do artigo e qualquer duvida pode entrar em contato pelo site www.mauriciojunior.org.