O título pode parecer demasiado confuso com a utilização de tantos termos, no entanto estou confiante que no fim do artigo, vai estar de acordo com a escolha.
Recentemente deparei-me com uma nova situação, por um lado necessitava de toda a interactividade e flexibilidade proporcionada pelo jQuery no cliente mas também queria continuar a utilizar no lado do servidor Microsoft ASP.NET de forma convencional, ou seja, eu precisava do melhor dos dois mundos.
Depois de executar alguns testes, encontrei rapidamente alguns entraves, limitações e complexidades, o que me levou à procura de uma solução simples e eficaz.
Deparei-me com um cenário em que o utilizador necessitava de preencher um formulário extenso, para tornar mais agradável a experiência do utilizador, para isso implementei vários plugins do jQueryUI, conforme se pode verificar nas imagens em baixo.
A informação a inserir é extensa e necessita de validação no lado do servidor, não se torna prático executar tudo isso postback atrás de postback até estar tudo correcto, utilizar update panels torna-se demasiado complexo para o tipo de validação necessário e a biblioteca Ajax do ASP.NET não é das mais agradáveis de utilizar quando necessitamos de performance, optei por isso experimentar utilizar o método Ajax disponibilizado pelo jQuery.
Para simplificar o artigo, e porque o que realmente interessa é o conceito, optei por criar um formulário de teste cujo objectivo é adicionar um cliente ao sistema.
Depois adiciona-se um novo item ao projecto, um Generic Handler
Visto de uma forma mais simplista, um Generic Handler é uma página ASP.NET que contém apenas um método e não suporta eventos nem controlos.
De seguida vamos adicionar um novo ficheiro JS e utilizando método Ajax da biblioteca jQuery, vai ser chamado o Generic Handler AdicionarClienteHandler.
A função Ajax é de simples implementação, como se pode verificar ao analisar o script apresentado.
$(document).ready(function () { //activa o plugin Tabs $(function () { $("#tabs").tabs(); }); //método adicionar cliente $('#btnAdicionar').click(function () { $.ajax({ url: '../../Handlers/AdicionarClienteHandler.ashx', data: $('form').serialize(), type: 'POST', success: function (data) { alert('Cliente adicionado com sucesso.'); $('#listClientes').append(data); }, error: function (data) { alert("Ocorreu um erro ao processar o seu pedido."); } }); }); });
O utilizador vai preencher o formulário e quando é executado o click sobre o botão adicionar, vai ser executado o script apresentado anteriormente.
Este script vai serializar todos os campos de input que se encontram dentro da tag <form> e enviar esta informação para o Generic Handler através de um POST executado de forma assíncrona.
Depois o Generic Handler vai processar a informação enviada, executar as suas validações e construir a resposta.
using System; using System.Linq; using System.Web; using System.Text; using System.Collections.Generic; using System.Collections.Specialized; namespace WebApplication1.Handlers { public class AdicionarClienteHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { var form = context.Request.Form; context.Response.ContentType = "text/html"; context.Response.Write(ProcessaFormulario(form)); } protected string ProcessaFormulario(NameValueCollection form) { string username, nome, email, telefone, telemovel, fax; nome = form["txtNome"]; username = form["txtUsername"]; email = form["txtEmail"]; telefone = form["txtTelefone"]; telemovel = form["txtTelemovel"]; fax = form["txtFax"]; var buildResponse = new StringBuilder(); buildResponse.AppendLine("<div class=\"DefaultRow\">"); buildResponse.AppendLine(string.Format("<h6>{0}</h6>", nome)); buildResponse.AppendLine(string.Format("<span class=\"DafaultRowLabel\">Username: {0}</span>", username)); buildResponse.AppendLine(string.Format("<span class=\"DafaultRowLabel\">Email: {0}</span>", email)); buildResponse.AppendLine(string.Format("<span class=\"DafaultRowLabel\">Telefone: {0}</span>", telefone)); buildResponse.AppendLine(string.Format("<span class=\"DafaultRowLabel\">Telemóvel: {0}</span>", telemovel)); buildResponse.AppendLine(string.Format("<span class=\"DafaultRowLabel\">Fax: {0}</span>", fax)); buildResponse.AppendLine("</div>"); return buildResponse.ToString(); } public bool IsReusable { get { return false; } } } }
A resposta por sua vez, é a informação do cliente formatada de acordo com a forma pretendida e pronta para ser adicionada à lista de clientes.
Tudo isto é executado de forma assíncrona, simples, eficaz e sem a necessidade de executar qualquer postback.
/*Versão JSON*/
Depois de verificar que surgiram alguns pedidos relativamente à utilização de JSON na resposta do Generic Handler, deixo aqui as alterações necessárias:
using System; using System.Linq; using System.Web; using System.Text; using System.Collections.Generic; using System.Collections.Specialized; using System.Web.Script.Serialization; namespace WebApplication1.Handlers { public class AdicionarClienteHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { var form = context.Request.Form; var serializer = new JavaScriptSerializer(); context.Response.Charset = "utf-8"; context.Response.ContentType = "application/json"; context.Response.Write(serializer.Serialize(JsonResponse(form))); } public List<string> JsonResponse(NameValueCollection form) { string username, nome, email, telefone, telemovel, fax; var lista = new List<string>(); nome = form["txtNome"]; username = form["txtUsername"]; email = form["txtEmail"]; telefone = form["txtTelefone"]; telemovel = form["txtTelemovel"]; fax = form["txtFax"]; lista.Add(nome); lista.Add(username); lista.Add(email); lista.Add(telefone); lista.Add(telemovel); lista.Add(fax); return lista; } public bool IsReusable { get { return false; } } } }
Como podemos verificar na imagem em baixo, a resposta é agora JSON
O projecto de teste aqui demonstrado , desenvolvido em Visual Studio 2010, está disponível para download aqui.
Referências:
http://api.jquery.com/serialize/
http://api.jquery.com/category/ajax/
http://msdn.microsoft.com/en-us/library/bb398986.aspx
Uma sugestão, não devolvas HTML na resposta mas um objecto JSON, e depois faz o binding em jQuery.
Outra seria usares serviços WCF com HTTP REST para teres mais flexibilidade
Cristóvão, tens toda a razão no teu comentário.
A forma mais correcta é devolver um objecto JSON.
É possível utilizar um WCF, um Webservice ou até decorar com [System.Web.Services.WebMethod()] um método no code-behind de uma página ASPX.
No entanto, o principal objectivo do artigo é demonstrar de forma simples e sucinta, uma das várias implementações possíveis para resolver o problema.
Obrigado pela tua contribuição.
Boa noite.
Cristóvao,
Você teria um exemplo com o objeto JSON com response?
Grato pela atenção.
Diego Teixeira
Diego,
Para obteres um JSON como resposta do Generic Handler, em vez de devolveres o HTML com a tua resposta, necessitas de serializar a informação, conforme o novo exemplo que coloquei no post.
Muito obrigado, Bruno.
Obrigado pelo artigo Bruno
Um erro que cometi num último projecto foi desenvolver uma plataforma muito baseada no AjaxControlToolkit e estou mais que arrependido pelo performance da aplicação, UpdatePanels para aqui e para ali, etc etc. O próximo passo é sem dúvida ir substituindo alguns componentes.
Obrigado pela dica, Bruno!
Estou fazendo a migração de um CMS em ASP para ASP.NET e o seu artigo foi bastante útil para mim.
Como ainda estou apredendo ASP.NET, gostaria de saber se possível, por que utilizar uma página .ashx ao invés de uma página .aspx normal.
Valeu, abraço!
Obrigado Rodolfo.
O ashx é um handler, enquanto que aspx é um webform. O aspx tem as funcionalidades necessárias para efectuar o rendering de uma página e o ashx não foi desenhado para esse fim.
Muito bom o artigo Bruno. Segue o javascript para quem quer usar o retorno JSON:
//método adicionar cliente
$(‘#btnAdicionar’).click(function () {
$.ajax({
url: ‘../../Handlers/AdicionarClienteHandler.ashx’,
data: $(‘form’).serialize(),
type: ‘POST’,
success: function (data) {
alert(‘Cliente adicionado com sucesso.’);
var html = ”;
html+= ” + data[0] + ”;
html+=’Username: ‘ + data[1] + ”;
html+=’Email: ‘ + data[2] + ”;
html+=’Telefone: ‘ + data[3] +”;
html+=’Telemóvel: ‘ + data[4] + ”;
html+=’Fax: ‘ + data[5] + ”;
html+=”;
$(‘#listClientes’).append(html);
},
error: function (data) {
alert(“Ocorreu um erro ao processar o seu pedido.”);
}
});
});
Como faço para persistir estas informações em um banco de dados e atualizar um gridview
Numa GridView de ASP.NET?
Bruno,
Muito bom o artigo ! Mas aproveitando a pergunta do Jean, gostaria de persistir os dados em um banco de dados e exibir em uma gridview ou quem sabe aproveitando a jQuery em uma jGrid.
Obrigado
Respondendo a pergunta, sim, em ASP.NET
A performance é o menor dos muitos problemas do AjaxControlToolkit.
Obrigado pelo artigo.
Primeiramente gostaria de agradecer pelo post que me foi muito útil.
Só fiquei com uma dúvida, fiz exatamente como explicado e funcionou, mas no meu form eu possuo um campo checkbox, e não consigo pegar se ele está check ou não.
Fiz isso e não está funcionando.
Ex:
bool restritivo = Convert.toBoolean(form["txtFax"]);
[txtFax] na verdade é ["restritivo"]
Como faria para pegar um arquivo html e com o jquery enviar o forma para um arquivo json quando for enviado o asp.net processar ele e enviar no formato json para que um jquery no mesmo arquivo html possa ler resposta?