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.

Criando um projeto ASP.NET MVC 4 para testes

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”).

Criando um projeto ASP.NET MVC 4 para testes

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.

Criando um novo 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.

Aplicação em execução

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).

Teste envolvendo a ordenação decrescente dos dados

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).

Testando a funcionalidade de paginação

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!