Asp.Net MVC – Preenchando campos da View a partir do JavaScript (JQuery, KnockoutJS, etc)    

Olá Pessoal!

Atualmente, todo bom desenvolvedor se preocupa com a experiência do usuário. Não é a toa que bibliotecas JavaScript, como JQuery, tem se popularizado tanto. Nós queremos dar a melhor experiência para o usuário e o único jeito é abusar de JavaScript e Ajax.

Porém, quando começamos a fazer uma interface muito rica, normalmente fazemos todo o controle da View no JavaScript, e acabamos fazendo muitos request para preencher uma única página.

Por exemplo, se eu estiver utilizando KnockoutJS, e minha página for um pouco mais complexa, meu ViewModel começará a ficar extenso. Veja por exemplo esse tutorial do próprio site do KnockoutJS, que apesar de ser simples, já demanda um pouco mais de JavaScript. Num exemplo real, o JavaScript fica imenso.

E como recuperar os dados do servidor e fazer esse Model ser renderizado na página? Muitas vezes fazemos como era possível no WebForms:

  1. Renderizamos a Página
  2. Requisitamos os dados via Ajax
  3. Retornamos os dados.
  4. Preenchemos o ViewModel

O problema é que essa solução, além de fazer dois Request, no mínimo, faz a página “piscar” geralmente, afinal, ela aparece momentaneamente sem os dados, e depois os dados aparecem.

Por exemplo, imagine o simples modelo abaixo:

   1: <script src="../../Scripts/knockout-1.3.0beta.js" type="text/javascript"></script>
   1:  
   2: <div data-bind="with: Autor">
   3:     <p>
   4:         Nome : <span data-bind="text: Nome"></span>
   5:     </p>
   6:     <p>
   7:         E-mail: <span data-bind="text: Email"></span>
   8:     </p>
   9:     <h2>
  10:         Posts</h2>
  11:     <ul data-bind="foreach:Posts">
  12:         <li><span data-bind="text:Titulo"></span>
  13:     </li></ul>
  14: </div>
  15: <script type="text/javascript"> 
  16:  
  17:     var meuModelo = {
  18:         Autor: {
  19:             Nome: "Frederico",
  20:             Email: "teste@teste.com",
  21:             Posts: [
  22:                     { Titulo: "Post 1" },
  23:                     { Titulo: "Post 2" },
  24:                     { Titulo: "Post 3" },
  25:                     { Titulo: "Post 4" }
  26:                 ]
  27:         }
  28:     } 
  29:  
  30:     ko.applyBindings(meuModelo);    
</script>

Caso eu queira receber os dados do servidor, no formato JSON, a primeira idéia que viria na cabeça seria a seguinte:

Criar uma Action que retorna os dados do banco de dados:

   1: public JsonResult ObterDados()
   2: { 
   3:    //Buscando no Banco de dados
   4:    var model = new
   5:    {
   6:        Nome = "Frederico",
   7:        Email = "teste@teste.com",
   8:        Posts = new object[]{
   9:            new {Titulo = "Post 1"},
  10:            new {Titulo = "Post 2"},
  11:            new {Titulo = "Post 3"},
  12:            new {Titulo = "Post 4"}
  13:        }
  14:    }; 
  15:    return Json(model, JsonRequestBehavior.AllowGet);
  16: } 

E na minha View, deveria invocar essa Acion de forma assíncrona:

   1: <script type="text/javascript"> 
   2: //faço outro request
   3: $.getJSON("Home/ObterDados", function (dados) {
   4:     //Preencho meus campos.
   5:     ko.applyBindings({ Autor: dados });
   6: });
   7: </script> 

Bom, na minha opinião, a solução ideal vem a seguir:

Renderizando JSON com ajuda do Json Helper

Apesar dos exemplos estarem com Knockout, utilizar o JSONHelper pode ajudar em qualquer situação, afinal, praticamente todos os plugins JQuery fazem uso de JSON.

A solução é muito simples, você não precisa criar duas Action para renderizar a página (Uma Index que apenas retorna a View, e outra que retorna os dados do Model assincronamente). Na própria Index você retorna os dados, como se fosse preencher os campos normalmente, mas na View renderiza os dados como JSON. Veja:

Na Action padrão eu retorno os dados:

   1: public ActionResult Index()
   2: {
   3:    ViewBag.Message = "Welcome to ASP.NET MVC!"; 
   4:    //Buscando no Banco de dados
   5:    var model = new
   6:    {
   7:        Nome = "Frederico",
   8:        Email = "teste@teste.com",
   9:        Posts = new object[]{
  10:            new {Titulo = "Post 1"},
  11:            new {Titulo = "Post 2"},
  12:            new {Titulo = "Post 3"},
  13:            new {Titulo = "Post 4"}
  14:        }
  15:    }; 
  16:    return View(model);
  17: } 

E na View utilizo o helper @Json:

   1: <script type="text/javascript">
   2: var meuModelo = {
   3:     //Faço o retorno da Action ser transformado em JSON
   4:     Autor: @Html.Raw(@Json.Encode(Model))
   5:     //Aqui poderia ter meus outros métodos e propriedades do ViewModel
   6: }
   7: //Preencho meus campos.
   8: ko.applyBindings(meuModelo);
   9: </script> 
 

E o resultado é o mesmo, porém, com apenas um Request, e com o código ligeiramente mais limpo:

image

Veja como o HTML é gerado, o JSON está renderizado como o esperado:

image

Apesar de não ter utilizado nenhum controle Input (textbox), a solução funciona da mesma forma com esses controles.

Bom pessoal, por hoje era isso. Espero que possa te ajudar.

Abraços!

9. setembro 2011 12:00 by Frederico B. Emídio | Comments (0) | Permalink

Utilizando Ajax com as facilidades do Asp.Net    

No último post, comentei que é uma tendência a utilização cada vez maior de Ajax nas aplicações Web. Particularmente acredito que a única utilidade de se utilizar WebForms em aplicações web hoje em dia é se for com uso de Ajax, junto com uma boa quantidade de JavaScript, para fazer a experiência do usuário ser cada vez melhor.

Tudo bem, podemos falar que é muito fácil de desenvolver, é só clicar e arrastar e tudo mais. Mas é fato que os usuários hoje cada vez mais querem uma experiência rica ao utilizar uma aplicação. Quanto mais próximo do desktop melhor. A única experiência próxima do desktop que existe utilizando o simples WebForm é a que o próprio desenvolvedor experimenta, que muitas vezes acredita que Web é só clicar e arrastar, como no WindowsForm, e que com um UpdatePanel tudo se resolve sem “refresh”.

Ledo engano. As telas vão ficando cada vez mais complexas, com mais requisições ao servidor, e ai um simples clique em um DropDownList, com AutoPostBack, demora 5 segundos para chegar em um botão, e o usuário já não fica tão satisfeito assim.

Este é o primeiro post de uma pequena série que vou falar da biblioteca Client Side do Asp.Net, e das capacidades Server Side que auxiliam no acesso ao Server dos códigos Client Side. O objetivo é que no final desta série você consiga desenvolver um site Asp.Net, com WebForm, que consiga proporcionar ao usuário um experiência pelo menos melhor que a normal.

Não utilizarei bibliotecas javascripts como JQuery, porque o objetivo aqui é falar das bibliotecas do Asp.Net.

PageMethods

Vamos começar falando de PageMethods, uma técnica que ainda não é muito utilizada no WebForms, mas que facilita muito a utilização de Ajax em páginas Asp.Net.

PageMethods são métodos de uma página WebForm, expostos como um WebMethods. Quando utilizamos PageMethods, a página web se torna um mini WebServices, inclusive, podendo ser utilizada por qualquer tecnologia que acesse métodos HTTP, como WCF, Java, ou um simples código JavaScript que faz uso do objeto XMLHttpRequest, como o JQuery.

Para criar um método HTTP em uma página é muito simples, basta criar um método estático decorado com o atributo WebMethod, localizado no namespace System.Web.Services. Eexemplo:

 [WebMethod]

        public static string Teste(string nome)
        {
            return string.Concat("Olá ", nome, ".");
        }

 Apenas assim já conseguiríamos utilizar este método método via XMLHttpRequest, ou pelo método Ajax do JQuery.

Mas para ficar interessante, é interessante adicionarmos o controle ScriptManager, do Asp.Net Ajax, à página, com a propriedade EnablePageMethods setada com o valor True:

<asp:ScriptManager runat="server" ID="maganger" EnablePageMethods="true"></asp:ScriptManager>

Desta forma, o Asp.Net criará um Proxy para o método na página, encapsulando no objeto PageMethods no ClientSide.

Para invocar o método, precisamos apenas chamar o método definido no ServerSide através do objeto PageMethods no Client Side, passando como parâmetro os parâmetros definidos no Server Side (nome caso do exemplo, o parâmetro nome), além de um método para receber o retorno no caso de sucesso e o retorno no caso de falha (exception):

PageMethods.Teste(“Frederico”,callbackSucesso,callbackErro);

O método de retorno de sucesso tem como parâmetros, o retorno do PageMethods, caso haja, como primeiro parâmetro, e os demais parâmetros são informações de contexto, informações de conexão, etc. Para hoje, precisamos apenas saber do primeiro parâmetro, o retorno do PageMethod Teste

No caso do retorno de falha, o primeiro parâmetro é a exceção, inclusive com StackTrace, para o momento precisamos apenas conhecimento do primeiro parâmetro também.

Para testarmos o método acima podemos fazer a seguinte página:

 

Ao clicarmos no botão Testar, a requisição irá assíncrona até o servidor e voltará, preenchendo o parágrafo de resposta:

 

Com isso já conseguimos ver o funcionamento básico de um PageMetho, porém, o mais legal é que um PageMethods te dá a possibilidade de trabalhar com classes complexas do .Net, ou seja, conseguimos enviar e receber classes de negócios por PageMethods, de forma totalmente transparente.

Imagine que temos um cadastro de pessoas, onde os dados necessários são Nome e e-mail, teremos uma classe assim:

O código abaixo, em HTML/Javascript, mostra como salvar esta classe com PageMethods, com a utilização de um objeto javascript criado com JSON:

 

Perceba que ao clicar no botão salvar:

 

Conseguimos colocar um breakpoint no PageMethods e verificar o conteúdo no lado do Server:

Com isso podemos utilizar qualquer coisa no lado do servidor, como o EntityFramework para persistência. E se quisermos retornar um classe, apenas temos que mudar o tipo do Retorno, que o método callback de sucesso retornará no primeiro parâmetro a classe oriunda do servidor.

Conclusão

A idéia deste post foi dar apenas uma introdução ao PageMethods, para que possamos começar a usar essa velha tecnologia que já está no Asp.Net desde a primeira versão do Asp.Net Ajax Framework, no .Net 2.0, mas que muita gente ainda desconhece.

Temos muitas peculiaridades que abordaremos em posts futuros. Espero que isto possa ajudar alguns de vocês que desconhecem esta tecnologia.

Abraços e até a próxima.

 

 

 

 

 

 

9. agosto 2010 08:37 by Frederico | Comments (5) | Permalink

Sobre mim

Minha Imagem

Meu nome é Frederico Batista Emídio, trabalho com desenvolvimento de sistemas profissionalmente a oito anos, porém, já faço sites pessoais a pelo menos dez anos.

Para saber mais clique aqui.

Páginas

Calendário

<<  novembro 2017  >>
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET