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

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