A exibição de informações num formato tabular é, certamente, uma necessidade mais do que frequente na esmagadora maioria das aplicações voltadas à Internet.
Muitos controles (proprietários ou gratuitos) foram desenvolvidos procurando atender a este tipo de demanda. Diversas dessas soluções foram construídas sob a tecnologia JQuery, o que torna mais fácil a integração destas a sites concebidos nas mais diferentes plataformas. O plugin Backgrid.js é uma biblioteca com estas características, o que o transforma numa alternativa viável para a implementação de grids em aplicações ASP.NET MVC.
Atualmente na versão 0.2.0 (Abril/2013), a biblioteca Backgrid.js se destaca por procurar fornecer suporte aos seguintes recursos:
- A leitura de informações no formato JSON, o qual é suportado pelas principais plataformas de desenvolvimento;
- A paginação dos dados vinculados a uma grid;
- A ordenação crescente/decrescente dos dados associados a uma grid, bastando para isto um simples clique no cabeçalho de uma coluna/campo;
- Mecanismos para inclusão, alteração e/ou exclusão de registros.
Maiores informações (inclusive instruções para download e utilização da biblioteca) podem ser obtidas através do link:
http://wyuenho.github.io/backgrid/
O objetivo deste artigo é abordar a utilização do plugin Backgrid.js em uma aplicação ASP.NET MVC, permitindo assim a construção de grids que contem com funcionalidades de paginação e ordenação de dados. Isto implicará no uso da tecnologia ADO.NET (acessando um banco de dados SQL Server) e de JSON durante a implementação do site para testes.
Criando a solução de exemplo
A aplicação apresentada neste artigo foi criada a partir do Visual Studio 2012 Professional, fazendo uso para isto do .NET Framework 4.5 e da versão 4.0 do ASP.NET MVC. O exemplo a ser implementado fará uso de um banco de dados SQL Server (Northwind) via ADO.NET, com a conversão do resultado de uma consulta a informações de clientes para o formato JSON; serão estes dados a base para o preenchimento da grid criada por meio do plugin Backgrid.js.
Para gerar o projeto de testes será necessário, dentro do Visual Studio, acessar o menu File, opção New e, por fim, a opção Project. Dentro da tela New Project (Figura 1) selecionar o template ASP.NET MVC 4 Web Application, preenchendo o campo Name com o nome da aplicação a ser gerada (“TesteGridMVC”, neste caso); no campo Location é possível ainda definir o diretório no qual serão criados os arquivos para este projeto.
Figura 1: Criando um projeto ASP.NET MVC 4 para testes
Aparecerá então uma janela como a que consta na Figura 2. Deverão ser escolhidos o template para a criação do projeto (selecionar “Internet Application”), assim como o Engine utilizado para a geração das Views (marcar a opção “Razor”).
Figura 2: Criando um projeto ASP.NET MVC 4 para testes
Configurando o acesso à base de dados
Para a obtenção das informações utilizadas pela aplicação de exemplo será empregado o banco de dados Northwind. Maiores informações sobre como habilitar esta base para uso no SQL Server 2012 podem ser encontradas no link:
http://msdn.microsoft.com/en-us/library/vstudio/8b6y4c7s.aspx
Com a base de dados já configurada, adicionar ao arquivo Web.config do projeto de testes a string de conexão “Nortwind” (conforme indicado na Listagem 1).
Listagem 1: Ajustes no arquivo Web.config da aplicação
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<connectionStrings>
<add name="Northwind"
connectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
...
</configuration>
Implementando as classes de acesso a dados
Com o projeto TesteGridMVC já criado e o acesso à base de dados devidamente configurado, chega o momento de prosseguir com a criação dos tipos empregados na manipulação de informações sobre clientes. As estruturas descritas nesta seção pertencerão à camada Model (namespace TesteGridMVC.Models).
Primeiramente será implementada a classe Cliente (Listagem 2). Foram definidos neste tipo (sob a forma de propriedades) o código do cliente, o nome da empresa, o responsável por negociações, o endereço da companhia, a cidade, o país, além do telefone para contatos.
Listagem 2: Classe Cliente
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TesteGridMVC.Models
{
public class Cliente
{
public string CodCliente { get; set; }
public string NomeCliente { get; set; }
public string Responsavel { get; set; }
public string Endereco { get; set; }
public string Cidade { get; set; }
public string Pais { get; set; }
public string Telefone { get; set; }
}
}
Já na Listagem 3 está o código referente à classe ClienteDAO. Este tipo baseia-se em um padrão conhecido Data Access Object (DAO), tendo por função centralizar o acesso à base de dados para a manipulação de informações sobre clientes.
Listagem 3: Classe ClienteDAO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;
namespace TesteGridMVC.Models
{
public class ClienteDAO
{
public List<Cliente> ObterInformacoesClientes()
{
List<Cliente> resultado = new List<Cliente>();
using (SqlConnection conexao =
new SqlConnection(ConfigurationManager
.ConnectionStrings["Northwind"].ConnectionString))
{
SqlCommand cmd = conexao.CreateCommand();
cmd.CommandText =
"SELECT CustomerID AS CodCliente " +
",CompanyName AS NomeCliente " +
",ContactName AS Responsavel " +
",Address AS Endereco " +
",City AS Cidade " +
",Country AS Pais " +
",Phone AS Telefone " +
"FROM Customers " +
"ORDER BY 2";
conexao.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
resultado.Add(new Cliente(){
CodCliente =
reader["CodCliente"].ToString(),
NomeCliente =
reader["NomeCliente"].ToString(),
Responsavel =
reader["Responsavel"].ToString(),
Endereco =
reader["Endereco"].ToString(),
Cidade =
reader["Cidade"].ToString(),
Pais =
reader["Pais"].ToString(),
Telefone =
reader["Telefone"].ToString()
});
}
reader.Close();
}
conexao.Close();
}
return resultado;
}
}
}
Será o método ObterInformacoesClientes (definido em ClienteDAO) que fornecerá os dados necessários para o preenchimento do controle gerado via plugin Backgrid.js. Quanto ao funcionamento desta operação, é possível observar:
- A partir da variável “conexao” (instância do tipo System.Data.SqlClient.SqlConnection) é estabelecida uma conexão com a base de dados utilizada pela aplicação de exemplo (empregando para isto a string de conexão “Northwind”);
- A referência de nome “cmd” (objeto do tipo System.Data.SqlClient.SqlCommand) representa a instrução SQL que fará a consulta à tabela de clientes;
- Ao se invocar o método ExecuteReader do objeto associado à variável “cmd” uma nova instância da classe SqlDataReader (namespace System.Data.SqlClient) é gerada. Será por meio desta referência que os diferentes registros serão lidos, com a conversão de tais informações em instâncias do tipo Cliente;
- Os objetos da classe Cliente são armazenados em uma coleção, a qual será devolvida como resultado da execução do método ObterInformacoesClientes.
Implementando o Controller que processará informações de clientes
Com os tipos da camada Model já definidos, deve-se proceder agora com a implementação do Controller que retornará os dados no formato JSON (possibilitando assim o preenchimento da grid que será criada através da biblioteca Backgrid.js).
JSON (sigla do inglês "Javascript Object Notation") é um formato aberto que torna possível a serialização de objetos como texto, representando uma opção ao padrão XML na transferência de informações através de uma rede. Este padrão é empregado costumeiramente em aplicações Web que utilizam recursos em AJAX e outros mecanismos de Javascript/JQuery.
Um objeto em JSON é composto por pares de informações, com cada um destes possuindo um identificador (string que identifica o nome de propriedade) e seu respectivo valor. Os seguintes tipos de dados podem ser empregados para a representação de valores em JSON: Numeric, String, Boolean, Array (os diversos elementos devem estar separados por vírgula e constando dentro de colchetes), e null.
A Listagem 4 demonstra um exemplo de objeto contendo dados relativos a uma empresa hipotética, com as informações estando de acordo com o padrão JSON.
Listagem 4: Exemplo de objeto já convertido para o formato JSON
{
"RazaoSocial" : "ACME Fabril Ltda.",
"NomeFantasia" : "ACME",
"NumeroFuncionarios" : 10627,
"Localizacao" :
{
"Endereco" : "Avenida 9 de Julho, 123",
"Cidade" : "São Paulo",
"Estado" : "SP",
"CEP" : "01234-567"
},
"Contatos" :
[
{
"Nome" : "João da Silva",
"Telefone" : "(11)3555-1234"
},
{
"Nome" : "José de Oliveira",
"Telefone" : "(11)3555-4567"
}
]
}
Um novo Controller pode ser criado por meio da janela Solution Explorer: para isto, clicar com o botão direito do mouse sobre a pasta Controllers, selecionando em seguida no menu de atalho o item Add, opção Controller. Aparecerá então a janela Add Controller; preencher o campo Controller Name com o valor "ClienteController" (Figura 3), enquanto em Template deverá estar marcada a opção "Empty MVC Controller.
Figura 3: Criando um novo Controller
Na Listagem 5 está a implementação da classe ClienteController. Foi definido neste Controller apenas a Action ObterInformacoesClientes, a qual devolverá como resultado de sua execução dados (já no formato JSON) a respeito de todos os clientes cadastrados na base Northwind.
Listagem 5: Classe ClienteController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TesteGridMVC.Models;
namespace TesteGridMVC.Controllers
{
public class ClienteController : Controller
{
[HttpGet]
public JsonResult ObterInformacoesClientes()
{
List<Cliente> informacoesClientes =
new ClienteDAO().ObterInformacoesClientes();
return this.Json(
informacoesClientes,
JsonRequestBehavior.AllowGet);
}
}
}
No que se refere à maneira como a Action ObterInformacoesClientes foi implementada, é possível destacar:
- O uso do atributo HttpGetAtribute (namespace System.Web.Mvc). Isto indica, basicamente, que a Action em questão será acessada através de requisições HTTP do tipo GET;
- O retorno do método ObterInformacoesClientes é uma instância da classe JsonResult (namespace System.Web.Mvc). Objetos deste tipo são gerados invocando-se o método Json (definido na classe básica System.Web.Mvc.Controller), o qual transforma um objeto gerado em .NET para o equivalente no formato JSON. O primeiro parâmetro da operação Json corresponde à referência que será convertida para o padrão JSON; já o segundo argumento deverá receber o valor de enumeration JsonRequestBehavior.AllowGet, de maneira que mecanismos de Javascript possam obter os dados disponibilizados pela Action através de instruções próprias para este fim.
OBSERVAÇÕES:
- Por convenção, nomes de classes que representam atributos terminam com o sufixo Attribute. A utilização de expressões que envolvam um atributo vinculando o mesmo a uma estrutura de código dispensa o uso de tal sufixo ao final do nome. Logo, ao se empregar o atributo HttpGetAttribute emprega-se apenas “HttpGet” na Action a ser marcada com o mesmo.
- Actions que atendam a requisições do tipo GET em um Controller MVC poderão não estar associadas a um atributo HttpGetAttribute (que é opcional). Solicitações de outros tipos precisarão obrigatoriamente estar marcadas com um atributo que represente a ação HTTP equivalente (HttpPostAttribute para uma requisição POST).
- Por questões de simplificação, a implementação do Controller HomeController foi omitida. As Actions desta classe não possuem nenhuma instrução complexa que necessite detalhamento (o código-fonte de HomeController pode ser obtido a partir do material para download deste artigo).
Implementando a grid de consulta a informações de clientes
A Listagem 6 corresponde à implementação da View Index. A página HTML resultante do processamento desta estrutura conterá a grid com dados de clientes.
Listagem 6: View Index.cshtml
@section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>Exemplo de utilização de grid -
plugin Backgrid.js</h1>
</hgroup>
</div>
</section>
}
<link rel="stylesheet" href="~/Content/backgrid.css" />
<link rel="stylesheet" href="~/Content/backgrid-paginator.css" />
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script src="~/Scripts/underscore.js"></script>
<script src="~/Scripts/backbone.js"></script>
<script src="~/Scripts/backgrid.js"></script>
<script src="~/Scripts/backbone-pageable.js"></script>
<script src="~/Scripts/backgrid-paginator.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var Cliente = Backbone.Model.extend({});
var PageableClientes = Backbone.PageableCollection.extend({
model: Cliente,
url: "/Cliente/ObterInformacoesClientes",
state: {
pageSize: 7
},
mode: "client"
});
var clientes = new PageableClientes();
var columns = [
{
name: "CodCliente",
label: "Código",
cell: "string",
editable: false
},
{
name: "NomeCliente",
label: "Cliente",
cell: "string",
editable: false
},
{
name: "Responsavel",
label: "Responsável",
cell: "string",
editable: false
},
{
name: "Endereco",
label: "Endereço",
cell: "string",
editable: false,
sortable: false
},
{
name: "Cidade",
label: "Cidade",
cell: "string",
editable: false
},
{
name: "Pais",
label: "País",
cell: "string",
editable: false
},
{
name: "Telefone",
label: "Telefone",
cell: "string",
editable: false,
sortable: false
}
];
// Inicializa uma instância da grid
var grid = new Backgrid.Grid({
columns: columns,
collection: clientes,
footer: Backgrid.Extension.Paginator
});
// Inicia a renderização da grid
$("#gridClientes").append(grid.render().$el);
// Obtém os dados acionando ClienteController
clientes.fetch();
});
</script>
<h3>Clientes cadastrados</h3>
<div id="gridClientes">
</div>
Basicamente, a construção de grids através do plugin Backgrid.js envolve o uso de algumas bibliotecas Javascript, além de folhas de estilo CSS empregadas na renderização destes controles. Conforme pode ser observado no início da Listagem 6, estão sendo referenciados:
- Os arquivos de estilo backgrid.css e backgrid-paginator.css, os quais definem como serão a aparência de grids com paginação ao se empregar a biblioteca Backgrid.js;
- A biblioteca de scripts JQuery (arquivo jquery-1.7.1.js);
- As bibliotecas Underscore.js (arquivo underscore.js) e Backbone.js (arquivo backbone.js), as quais formam a base a partir da qual o plugin Backgrid.js foi concebido;
- A própria biblioteca Backgrid.js (arquivo backgrid.js), além dos mecanismos para a paginação de resultados em grids (arquivos backbone-pageable.js e backgrid-paginator.js).
Quanto às instruções que irão gerar a grid com informações de clientes, notam-se os seguintes pontos:
- Inicialmente é criada uma classe Javascript de nome Cliente (via instrução Backbone.Model.extend), a qual corresponde ao modelo (uma espécie de "classe de dados") utilizado na manipulação dos diferentes objetos/registros serializados no formato JSON;
- Já a classe PageableClientes (gerada através da instrução Backbone.PageableCollection.extend) será empregada em operações que envolvam a paginação da coleção de objetos contendo informações de clientes. Para tanto, foram informados na criação deste tipo a classe de modelo (parâmetro "model"), o endereço para se obter os dados no formato JSON (parâmetro "url"), o número de registros a serem exibidos por página (parâmetro "pageSize"), além do local em que ocorrerá a paginação dos registros (parâmetro "mode"; o valor "client" indica que este processo acontecerá do lado cliente, ou seja, a partir do browser do usuário);
- As configurações das diferentes colunas que farão parte da grid estão vinculadas ao array de nome "columns". Para a geração dos objetos vinculados a este último, estão sendo preenchidos os parâmetros "name" (nome da propriedade/campo da instância serializada no formato JSON), "label" (texto que aparecerá no cabeçalho da grid), "cell" (tipo da coluna), "editable" (indica se a coluna será ou não editável; o default é o valor "true") e "sortable" (define se haverá ou não a possibilidade de ordenação para uma determinada coluna; o valor default para esta configuração também é "true");
- Uma instância da grid será então criada por meio da instrução Backgrid.Grid. Para isto, foram preenchidos os parâmetros "columns" (configurações das colunas visíveis na grid), collection (instância do tipo PageableClientes) e "footer" (controle de página que ficará no rodapé da grid);
- A invocação do método render a partir da instância da grid fará com que se produza o código HTML para este controle; já a chamada ao método fetch da coleção contendo informações de clientes preencherá a grid, além de levar em conta questões como as funcionalidades de paginação e ordenação de valores.
Executando a aplicação de testes
Iniciando a execução do site de testes, será exibida uma tela como a que consta na Figura 4; as informações sobre clientes já se encontram devidamente paginadas neste momento.
Figura 4: Aplicação em execução
Na Figura 5 é apresentado um exemplo em que os dados estão ordenados de maneira decrescente (neste caso, por nome de cliente).
Figura 5: Teste envolvendo a ordenação decrescente dos dados
Por fim, a Figura 6 demonstra o uso da funcionalidade de paginação. Importante salientar que o uso deste recurso e ainda, a execução do processo de ordenação, não forçam a execução de uma nova consulta à base (estas ações são realizadas sobre os dados no formato JSON obtidos uma única vez, com isso acontecendo durante o carregamento da página).
Figura 6: Testando a funcionalidade de paginação
Conclusão
Procurei com este artigo demonstrar como empregar o plugin Backgrid.js para a construção de grids em aplicações ASP.NET MVC. Para situações que contemplem um pequeno volume de informações, esta biblioteca de scripts pode se revelar como bastante útil na exibição/manipulação de dados num formato tabular.
Entretanto, alternativas diferentes precisarão ser buscadas em cenários que envolvam a utilização de grandes massas de dados. A seguir estão listadas outras opções de bibliotecas/suítes de componentes que permitem a utilização de grids em conjunto com o framework MVC :
Com exceção do plugin WebGrid que é disponibilizado gratuitamente pela própria Microsoft, todas as demais opções citadas envolvem a aquisição de uma licença junto aos seus respectivos fornecedores
Espero que o conteúdo aqui apresentado possa lhe ser útil em algum momento. Até uma próxima oportunidade!