Arquivos da categoria: JQuery

Chamadas XMLHttpRequest (AJAX) enviando JSON para páginas aspx ou GenericHandler – Deserialização manual

json160 csharplogoOlá pessoal,

Realmente é muito simples realizar uma chamada XMLHttpRequest (AJAX) para um WebMethod ASP.NET. E mais fácil ainda é enviar dados no formato JSON para o WebMethod, pois por padrão o WebMethod deserealizada a string JSON conforme seus parâmetros.

Mas quando não temos um WebMethod para receber os dados no formato JSON e fazer todo o trabalho de sujo de deserialização? Por exemplo, ao fazer chamadas XMLHttpRequest para uma página ou um Generic Handler passando dados no formato JSON. Nesta situação é necessário realizar a deserialização dos dados manualmente, vamos a um exemplo.

Chamada XMLHttpRequest no lado cliente:

var request = $.ajax({
type: "POST",
dataType: "json",
url: "/meusite/processa.ashx",
cache: false,
data: JSON.stringify({ p1: "oi", p2: 1000, vet: [{ vp1: {vp2: "xxxx"}},2] })

});

request.done(function (r) {
console.log(r);
});

request.fail(function () {
alert("Não foi possível processar sua requisição.");
});

O código acima utiliza a biblioteca jQuery para encapsular o uso da biblioteca javascript XMLHttpResquest e enviar dados ao servidor. Em sua configuração, a propriedade “URL” indica um GenericHandler no servidor (processa.ashx), mas que também pode ser substituído por uma página aspx. E a propriedade “data” foi configurada com um objeto literal com propriedades simples e complexas, que antes de ser enviado ao servidor será transformando numa string JSON pelo método JSON.stringify.

No lado servidor (no GenericHandler ou no método page_load da página), a recepção dos dados fica assim:

JavaScriptSerializer jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();

Dictionary<string, object> values = jss.Deserialize<Dictionary<string, object>>(json);

string p1 = values["p1"].ToString();
int p2 = Convert.ToInt32(values["p2"]);

var vet = (ArrayList)values["vet"];
var vp1 = ((Dictionary<string, object>)vet[0])["vp1"];
var vp2 = ((Dictionary<string, object>)vp1)["vp2"];

No código de servidor acima, a propriedade InputStream do objeto Request representa o conteúdo do corpo de entrada de conteúdo HTTP vindo do cliente, portanto, representa a string JSON enviada pelo cliente.

O inputString é recuperado e deserializado em um objeto Dictionary (espécie de lista indexada por chaves). Cada propriedade da string JSON torna-se uma chave do dicionário, sendo facilmente acessada:

int p1 = values["p1"].ToString();
int p2 = Convert.ToInt32(values["p2"]);

E também podemos acessar estruturas JSON mais complexas, como é o caso da propriedade “vet”, que mantém um vetor, cujo seu índice 0 (zero) contém outro objeto JSON.

vet: [{ vp1: {vp2: "xxxx"}},2]

Após recuperação do vetor, foi necessário converte o objeto de índíce 0 (zero) em outro Dictionary, desta forma, as propriedades do objeto contido no índice 0 (zero) da propriedade “vet” são acessadas por chaves do Dictionary.

var vp1 = ((Dictionary<string, object>)vet[0])["vp1"];
var vp2 = ((Dictionary<string, object>)vp1)["vp2"];

E fim.

UpdatePanel e JQuery

Para quem usa ASP.NET é comum o uso do UpdatePanel para realizar atualizações parciais. Atualmente também é comum o uso JQuery.

O problema é quando os dois recursos devem conviver juntos. O problema que ocorre é que após a atualização parcial da página pelo UpdatePanel a implementação JQuery deixa de funcionar, provavelmente devido a estrutura da página ter mudado após a atualização.

Uma forma que encontrei, é executar as funções Javascript que usam JQuery novamente após a renderização pelo UpdatePanel.

No ASP.NET Ajax é possível gerenciar a renderização parcial da página através da classe PageRequestManager. A classe define eventos que podem ser usados na personalização da renderização parcial. O seu metódo getInstance() recupera sua instância atual/ativa e seu método add_endRequest permite adicionar uma chamada a uma função Javascript exatamente após o fim da renderização parcial, é neste momento que devemos chamar a função Javascript que mantem código JQuery.

Exemplo:

$(document).ready(function () {

	//Inicializando na após a carga da página
	inicializa();

	//função com o código JQuery
	function inicializa()
	{
		$("buttonX").click(function () {
			fazAlgumaCoisa();
		});
	}

	function fazAlgumaCoisa()
	{
		alert('Feito');
	}

	//Recuperando a instância ativa da classe PageRequestManager.
       var prm = Sys.WebForms.PageRequestManager.getInstance();
       if (prm != null) {
   	   //Registrando uma chamada a função inicializa() após o fim da renderização parcial da página.
           prm.add_endRequest(function () {
               inicializa();
           });
       }
})

Mais informações sobre a classe PageRequestManager em http://msdn.microsoft.com/pt-br/library/bb311028(v=VS.90).aspx

Até mais.

O poder de usar Visões Parciais (partial views) com JQuery

Estou tentando aprender como criar página Web usando o Pattnern MVC 3 que acompanha o VisualStudio 2010. E hoje aprendi algo que me fascinou (pois no ASP.NET tradicional não é tão simples), invocar WebUserControls em chamadas AJAX. Vamos lá.

Uma Partial View é uma espécie de WebUserControl do MVC, ou seja, é possível criar pedaços de código a serem reaproveitados posteriormente em outras páginas.

Com o MVC é possível invocar via chamadas AJAX (neste caso com JQuery) Partial Views, ou seja, de forma simples posso via Ajax trazer o conteúdo da View que está no servidor.

A primeira coisa é criar a referência para biblioteca JQuery numa View normal ou MasterPage. E depois criar a Partial View e seu respectivo Action Controller.

Partial View OutroCurso.ascx:


<table cellpadding="0" cellspacing="0" style="width: 608px">
    <tr>
        <td style="width: 288px">
            Se sim, qual curso?<br />
            <%:Html.TextBox("txtQualCurso", "", new { maxlength = "10", style = "width:264px" })%>
        </td>
        <td>
            Em qual instituição?<br />
            <%:Html.TextBox("txtQualInstituicao", "", new { maxlength = "10", style = "width:264px" })%>
        </td>
    </tr>
</table>

Action Controller da Partial View OutroCurso.ascx:


public ActionResult OutroCurso()
{
    return PartialView();
}

E por fim, falta fazer a chamada AJAX para a Partial View acima dentro de uma View normal ou MasterPage.

A ideia do código abaixo é que o usuário ao selecionar o radiobutton SIM, apareçam outros campos a serem preenchidos (a Partial View). Observe que cada radionbutton em seu evento onclick chama a função JavaScript loadPartialViewOutroCurso, responsável por usar o método Load disponível na biblioteca JQuery para invocar a Partial View no servidor.

Possui outro curso superior?<br />
<%:Html.RadioButton("rblOutroCurso", "N", false, new { onclick = "loadPartialViewOutroCurso('N')" })%> Não
<%:Html.RadioButton("rblOutroCurso", "S", false, new { onclick = "loadPartialViewOutroCurso('S')" })%> Sim
<div id="divOutroCurso"></div>

<script type="text/javascript">

    function loadPartialViewOutroCurso(opcao) {

        if (opcao == 'S')
            $('#divOutroCurso').load('/Solicitacao/OutroCurso');
        else $('#divOutroCurso').html("");
    }

</script>

A URL a “/Solicitacao/OutroCurso” é a rota para o Action (OutroCurso) do Controller (Solicitacao) que mantém a Partial View.

Bom né?

Abraço e até a minha próxima descoberta no mundo MVC.

Retornar dados no formato JSON usando ASP.NET

Olá pessoal.

Com o advento das chamadas assíncronas diretamente do cliente ao servidor via Javascript, muitas vezes é necessário retornar ao cliente dados estruturados,  que pode ser uma estrutura XML, uma simples string separada por um caractere especial, ou ainda no formato JSON.

Uma boa opção devido sua padronização e facilidade de manipulação é o formato JSON.

Serializar um objeto que é uma instância de uma classe para o formato JSON no C# é bem simples. O problema é quando queremos serializar dados que não representam um objeto de instancia de classe. Neste caso, a técnica mais comum é concatenar strings formando a estrutura desejada (já fiz muito isso), além de complicar uma futura manutenção, não é elegante.

No C# podemos criar objetos de tipo anônimos (anonymous types), definir sua estrutura e dados, e depois serializar para o formato  JSON enviando tudo  ao cliente.

Exemplo de criação de um vetor de tipo de anônimo e com dados:

var vetorAnonimo = new object[] { new { nome = "nome 1", id = 1 },
                                  new { nome = "nome 2", id = 2 }};

Com o objeto anônimo definido e carregado é possível fazer sua serialização para enviar ao cliente:

using System.Web.Script.Serialization;

JavaScriptSerializer js = new JavaScriptSerializer();
string strJson = js.Serialize(vetorAnonimo);

Pronto. É só devolver a variável strJson para a função de callback no Javascript/JQuery e manipular o retorno.

Veja como chega no cliente o vetor serializado, uma string estruturada no formato JSON. Lindo!!!

[{"nome":"nome 1","id":1},{"nome":"nome 2","id":2}]

Este post teve ajuda do @victorvhpg ninja do JQuery.

Adicionar marca d’ água em inputs text com JQuery

Olá pessoal.

Neste post vou explicar como aplicar marca d’ água em inputs do tipo text usando a biblioteca JQuery.

Vamos lá.

Baixe a biblioteca JQuery em http://www.jquery.com/ e adicione ao projeto.

O código abaixo (Javascript e com uso da JQuery) aplica o feito de marca d’ água.  Cole o código num arquivo arquivo Javascript (.js) associado ao projeto.

jQuery(document).ready(function () {

    //recuperando todos os inputs que tenham um atributo data-marcadagua.
    var inputs = $('*[data-marcadagua]')

    //tratando CADA input recuperado na linha acima.
    jQuery.each(inputs, function () {

        //se o input atual não tem valor, então aplica a marca d' água
        if (jQuery.trim($(this).val()) == '') {
            aplicaMarca($(this));

        }

        //adicionando os manipuladores para os eventos de entrada e saída em cada input.
        $(this).bind('focusin',
								function () {
                                    //revomendo a marca d' água quando o input ganha o foco.
								    if ($(this).val() == $(this).attr('data-marcadagua')) {
								        limpaMarca($(this))
								    }
								}
						);
        $(this).bind('focusout',
								function () {
                                    //aplicando a marca d' água quando o input perde o foco e não tem valor.
								    if (jQuery.trim($(this).val()) == '') {
								        aplicaMarca($(this));
								    }
								}
					   );

    });

    function aplicaMarca(input) {
        input.css('font-style', 'italic');
        input.css('color', '#666');
        input.val(input.attr('data-marcadagua'));
    }

    function limpaMarca(input) {
        input.css('font-style', '');
        input.css('color', '');
        input.val('');
    }

});

No HEAD da página HTML, faça a vinculação da biblioteca JQuery e do arqvivo de script com o código acima.

<head>
<title></title>
<script src="jquery.js" type="text/javascript"></script>
<script src="marcadagua.js"></script>
</head>

A ideia aqui e adicionar aos inputs text da página um atributo chamado data-marcadagua, e o valor seu valor será o texto da marca d’ água.

Valor 1:
<input id="Text1" type="text" data-marcadagua="1 - Digite algo aqui..." value="Já tenho valor"/>
<br />
<br />
Valor 2:
<input id="Text2" type="text" data-marcadagua="2 - Digite algo aqui..."/>
<br />
<br />
Valor 3:
<input id="Text3" type="text" data-marcadagua="3 - Digite algo aqui..."/>
<br />
<br />
Valor 4:
<input id="Text4" type="text" data-marcadagua="4 - Digite algo aqui..."/>

No exemplo acima usei diretamente um input HTML. Para usar no controle TextBox do ASP.NET, no evento Page_Load utilize o método Add da propriedade Attribute.

protected void Page_Load(object sender, EventArgs e)
{
    TextBox1.Attributes.Add("data-marcadagua", "5 - Digite algo aqui...");
}

O resultado final:

Baixe aqui o exemplo completo.

Até mais…

Criando uma janela Popup estilo Facebook com JQuery e ASP.NET.

O legal de usar o Facebook é copiar as ideias de suas implementações e aplicá-las em nossos projetos. 😛

Vou mostrar como fiz para criar uma janela Popup parecida com as que são usadas no Facebook. Acho que ficou legal :-).

Primeiramente, no projeto ASP.NET devemos criar um arquivo do tipo Generic Handler. O Generic Handler é como se fosse uma página ASP.NET mais leve, pois não tem interface HTML e eventos no servidor, etc. Possui apenas um método, o ProcessRequest(HttpContext context) que é responsável por processar as requisições que chegam.

No método ProcessRequest deve ser codificado o HTML que será enviado à página que fez a requisição ao Generic Handler.

public class HandlerJanelaExemplo : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        string containerId = "#" + context.Request.QueryString["containerId"];

        string html = @"
            <div class=""divPopup""
                    style=""left: 323.5px; top: 145.5px; width: 600px; position: fixed; z-index: 10001;"">
                    <div style=""margin: 10px"">
						AQUI VOCÊ COLOCA O TÍTULO DA JANELA
                        <div style=""overflow: auto; height: 150px"">
                            AQUI VOCÊ COLOCA CONTEÚDO DA JANELA
                        </div>
                    </div>
                <div style=""width: 590px; background-color: #CCCCCC; text-align: right; padding: 5px;"">
                    <input type=""button"" value=""Fechar"" onclick=""@acaoFechar"" class=""botaoFerramenta""/>
                </div>
            </div>";

        //DEFININDO A AÇÃO DO BOTÃO FECHAR (SIMPLEMENTE LIMPA O HTML DO SPAN DA PÁGINA QUE REQUISITOU A JANELA).
        string acaoFechar = "$('" + containerId + @"').html('')";
        html = html.Replace("@acaoFechar", acaoFechar);

        context.Response.ContentType = "text/plain";
        context.Response.Write(html);
        context.Response.Flush();
        context.Response.End();
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Na página HTML que vai chamar a janela Popup deve existir um link e um elemento span. O link irá chamar uma função Javascript que utilizará JQuery para fazer uma requisição ao Generic Handler criado anteriormente. E o Generic Handler retornará o HTML contendo a janela Popup para função Javascript, que por sua vez atualizará o elemento span.

Código HTML da página.

<form id="form1" runat="server">
<div>
    <h1>Minha Página</h1>
    <br />
    <br />
    <asp:HyperLink ID="hlkJanela" runat="server" NavigateUrl="javascript:;">Chamar janela...</asp:HyperLink>
    <span id="spanPopup"></span>
</div>
</form>

Na página é necessário associar a função Javacript ao link pelo C#.

protected void Page_Load(object sender, EventArgs e)
{
    hlkJanela.Attributes.Add("onclick", "chamarJanela()");
}

A função Javascript usa JQuery para fazer a requisição ao Generic Handler. A informação URL recebe o endereço do Generic Handler e como parâmetro o ID do elemento span. O ID do elemento span será usado dentro do Handler para implementação do botão fechar da Popup.

function chamarJanela() {
    $.ajax({
        type: "GET",
        url: "HandlerJanelaExemplo.ashx?containerId=spanPopup",
        dataType: "text",
        success: function (retorno) {
            $("#spanPopup").html(retorno);

        },
        error: function (retorno) {
            alert('Erro');
        }
    });
}

Veja o resultado.

E é isso pessoal. É um exemplo bem simples que pode ser evoluido para uma solução robusta.
Baixe o exemplo para ver os detalhes da implementação.

Até mais…