Este artigo trata de algo que hoje está bem difundido, que são as transmissões de dados de forma assíncrona.
Assíncrono
Uma chamada assíncrona ocorre de forma intermitente em vez de uma chamada única e contínua.
Imagine uma ligação telefônica, ela é bilateral. A mesma coisa acontece com essas chamadas, um processo não espera outro acabar para ser iniciado. Exige cuidado, pois muitas chamadas perdidas devem ter seus receptores definidos e controlados, mas o ganho para uma aplicação é superior às chamadas síncronas.
Neste artigo está a proposta de fazer um sistema simples de cadastro de contatos com requisições assíncronas, permitindo cadastrar e editar os registros.
Claro que isso implicará em diversos outros problemas e até um pouco mais de trabalho, porém teremos o controle do que está sendo feito e a facilidade em tornar necessidades dinâmicas no form e não ter dores de cabeça com isso.
Por que Utilizar
Para quem programa com WebForms sabe que os controles do ASP.Net são de certa forma controladores. Quando surge a necessidade de maior usabilidade do lado do cliente, com conteúdos dinâmicos e até mesmo campos dinâmicos usando jQuery, começam os problemas. O postback realizado pelos componentes do ASP.net não respeita os objetos que foram criados dinamicamente, pois o ASP.net tem os campos registrados no seu HTML e as informações de cada campo e componente gravados no ViewState. Portanto tudo que esteja fora disso deverá ser tratado manualmente.
Então para quem busca um pouco mais de liberdade na hora de desenvolver (e não quer partir para o MVC) pode construir aplicações WebForms sem depender dos componentes de página, assim como reduzir drasticamente o ViewState da aplicação e consequentemente tornar a aplicação mais leve.
Codificar
Primeiramente vamos incluir o jQuery na Master Page utilizando, por exemplo, o jQuery provido pelo link do Google.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script>
Com o jQuery na página, o próximo passo é aprontar o layout da tela.
<input type="hidden" id="hdnID" />
<div id="main">
<fieldset>
<legend>Criar Contatos</legend>
<div class="divRow">
<div class="divLabel">
<label>
Nome :
</label>
</div>
<div class="divControl">
<input type="text" id="txtNome" maxlength="50" /></div>
</div>
<br />
<div class="divRow">
<div class="divLabel">
<label>
Telefone :</label></div>
<div class="divControl">
<input type="text" id="txtTelefone" maxlength="10" /></div>
</div>
<br />
<div class="divRow">
<div class="divLabel">
<label>
Celular</label></div>
<div class="divControl">
<input type="text" id="txtCelular" maxlength="10" />
</div>
</div>
<br />
<div class="divRow">
<div class="divLabel">
<label>
E-mail</label></div>
<div class="divControl">
<input type="text" id="txtEmail" maxlength="30" /></div>
</div>
<br />
<div class="divRow" style="padding-left: 135px;">
<input type="button" id="btnSalvar" value="Salvar" />
<input type="button" id="btnAlterar" value="Alterar" />
<input type="button" id="btnCancelar" value="Cancelar" />
</div>
</fieldset>
<br />
<fieldset>
<legend>Contatos Inseridos </legend>
<table id="tblContatos" cellpadding="2px" class="table">
<tr>
<th>
Nome
</th>
<th>
Email
</th>
<th>
Celular
</th>
<th>
Telefone
</th>
<th>
Editar
</th>
</tr>
<tbody id="tbody">
</tbody>
</table>
</fieldset>
</div>
Com a tela de cadastro montada, vamos codificar o primeiro evento.
Codificar o botão Salvar
Primeiramente vamos codificar o click do botão Salvar. Ao clicar nesse botão o sistema irá efetuar a validação dos campos Nome e Email, verificando foram preenchidos e no caso do Email se foi preenchido corretamente.
function Obrigatoriedade() {
var txtNome = $('#txtNome');
var txtEmail = $('#txtEmail');
var msg = '';
if (txtNome.val() === '') msg += "Preencha o Nome.";
if (!ExpValidateEmail(txtEmail.val())) msg += "Preencha o Email válido.";
if (msg != '') { alert(msg); return false; }
else return true;
}
function Salvar() {
var dataString = JSON.stringify({
nome: $('#txtNome').val(),
telefone: $('#txtTelefone').val(),
celular: $('#txtCelular').val(),
email: $('#txtEmail').val()
});
CallAjax('Service/AgendaService.asmx/Add', dataString);
}
$('#btnSalvar').click(function () {
var sucess = Obrigatoriedade();
if (sucess) {
Salvar();
AppendGrid();
}
});
O nosso Salvar fará o envio das informações em tela para um método chamado CallAjax. Esse método recebe o caminho do nosso serviço web, os parâmetros que serão enviados e uma função de retorno.
Segue o código abaixo.
function CallAjax(serviceFullPath, dataString, sucessCallBack) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: serviceFullPath,
data: dataString,
dataType: "json",
async: true,
success: sucessCallBack
});
}
O jQuery Ajax ao receber a requisição do botão salvar, procura e chama o serviço web e manda as informações para o método correspondente. No caso do botão salvar o método chamado foi o Add.
Antes de seguir para o código do Add devemos criar uma classe correspondente para nossa agenda.
public class Agenda : AgendaBLL
{
public int ID { get; set; }
public string Nome { get; set; }
public string Telefone { get; set; }
public string Celular { get; set; }
public string Email { get; set; }
public void Salvar()
{
base.SalvarAgenda(this);
}
public List<Agenda> Select()
{
return base.Select() as List<Agenda>;
}
public Agenda First()
{
return base.First(this);
}
public bool Update()
{
return base.Update(this);
}
}
public abstract class AgendaBLL
{
protected void SalvarAgenda(Agenda agenda)
{
PersistAgenda.Add(agenda);
}
internal IList Select()
{
return PersistAgenda.Select();
}
internal Agenda First(Agenda agenda)
{
return PersistAgenda.First(agenda);
}
internal bool Update(Agenda agenda)
{
return PersistAgenda.Update(agenda);
}
}
Veja que foi feita a classe Agenda e uma classe abstrata AgendaBLL. Agenda herda a AgendaBLL, como esse exemplo serve para exemplificar, não vamos discutir boas práticas aqui.
O método Add declarado dentro do serviço web faz o caminho dos dados, conforme a Listagem 6.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public void Add(string nome, string telefone, string celular, string email)
{
Agenda addAgenda = new Agenda();
addAgenda.Nome = nome;
addAgenda.Telefone = telefone;
addAgenda.Celular = celular;
addAgenda.Email = email;
addAgenda.Salvar();
}
E tem a classe que foi chamada de PersistAgenda, ela é nossa camada de dados. Como também não é o foco desse artigo, foi feita uma classe estática e os dados armazenados em lista.
public static class PersistAgenda
{
private static List<Agenda> _contacts;
static PersistAgenda()
{
GetInstance();
}
public static void GetInstance()
{
if (_contacts == null)
{
_contacts = new List<Agenda>();
}
}
public static void Add(Agenda objAgenda)
{
objAgenda.ID = _contacts.Count + 1;
_contacts.Add(objAgenda);
}
public static bool Remove(Agenda objAgenda)
{
return _contacts.Remove(objAgenda);
}
public static bool Update(Agenda objAgenda)
{
var index = _contacts.FindIndex(p => p.ID == objAgenda.ID);
if (index < 0) return false;
_contacts[index].Nome = objAgenda.Nome;
_contacts[index].Telefone = objAgenda.Telefone;
_contacts[index].Celular = objAgenda.Celular;
_contacts[index].Email = objAgenda.Email;
return true;
}
internal static IList Select()
{
return _contacts;
}
internal static Agenda First(Agenda agenda)
{
return _contacts.First(ag => ag.ID == agenda.ID);
}
}
Conclusão
Um sistema simples desse é tranquilo de ser desenvolvido totalmente assíncrono, uma aplicação mais robusta é claro que se torna inviável. O que deve ser retirado desse artigo é a facilidade das requisições e, como sugestão, para as novas aplicações utilizar esta forma.
Espero que este artigo acrescente conteúdo para quem ainda não conhecia o assunto.
Lembrando que poderíamos utilizar no lugar de WebService, um serviço em WCF e até mesmo o próprio code-behind da página (WebMethod), então pesquisem mais sobre assunto.