Vinicius Quaiato

{tecnologia, conceitos, negócios, idéias, práticas, .NET, ruby, osx, ios e algo mais}

ASP.NET MVC e Jquery Ajax


Atualmente aplicação web é quase sinônimo de Ajax. Não tem como criar uma boa aplicação sem Ajax.Se você acha que é possível é por que provavelmente você é egoísta ao ponto de não pensar em quem usa sua aplicação.

E hoje em dia Ajax é sinônimo de Jquery. Alguém discorda disso? A maioria dos desenvolvedores para web hoje nem sabem o que é XmlHttpRequest. Isso não é ruim, estou apenas mostrando que já não imaginamos realizar este tipo de trabalho manualmente. O lema do Jquery é: "Write less, do more." ou em bom português: "Escreva menos, faça mais".

Jquery

Jquery é uma biblioteca Javascript que tem por objetivo fornecer uma maneira simples, robusta e rápida de trabalhar com Ajax, manipulação do HTML/DOM, eventos e animações. É quase um padrão de mercado no que diz respeito a javascript(apesar de isso por si só não te qualificar como conhecedor de javascript hein!). Se você quiser conhecer mais sobre o Jquery dê uma olhada na vasta documentação e exemplos nos próprio site deles: http://docs.jquery.com/Main_Page

ASP.NET MVC

Como muitos sabem o ASP.NET MVC é o framework web Microsoft que trabalha com o padrão MVC. É muito comum aplicações ASP.NET MVC trabalharem junto com Jquery por temos o controle total do HTML gerado pelo ASP.NET MVC o que facilita sua manipulação via javascript.

ASP.NET MVC e Ajax com Jquery

Vamos falar um pouco da função ajax do Jquery em conjunto com o ASP.NET MVC.

Estafunção ajax realiza requests http de forma assíncrona. Isso quer dizer que podemos realizar processamentos de partes de nossa aplicação fora do request principal da página, evitando assim requests da página inteira para processar pequenas ações.V

Vamos imaginar o seguinte cenário:

Tela de listagem de produtos e na mesma tela queremos poder realizar a inserção de um novo produto.

A abordagem sem ajax é que o novo produto seja inserido e então toda a página seja recarregada com a listagem atualizada. Vou omitir algum código aqui para ser breve(todo fonte está disponível aqui no github.). Vamos ao controller:

public class HomeController : Controller {

    public ActionResult Index() {
        if(Session["products"] == null)
            Session["products"] = new SomeRepo().AllProducts().ToList();

        return View(Session["products"] as List<product>);
    }

    public ActionResult AddProduct(Product newProduct) {
        var products = Session["products"] as List<product>;
        products.Add(newProduct);

        return RedirectToAction("Index");
    }
}

Este controller está funcionando perfeitamente sem Ajax. É importante que tudo funcione sem ajax para só então colocarmos o novo comportamento com ajax. O código da view é bastante simples: (estou usando a session como um repositório fake para o exemplo, ok?)

@model IEnumerable<aspnetmvc_jquery_ajax.controllers.product>

<h2>Products</h2>

@using(Html.BeginForm("AddProduct", "Home", FormMethod.Post, new { id = "novo_produto" })){
    Descrição: @Html.TextBox("Description")
    Preço: @Html.TextBox("Price")
}

<table>
    <tr>
        <th>Description</th>
        <th>Price</th>
    </tr>
    @foreach (var item in Model) {
        <tr>
            <td>@item.Description</td>
            <td>@String.Format("{:F}", item.Price)</td>
        </tr>
    }

</table>

Tudo está funcionando perfeitamente. Mas cadê o ajax Vinicius? Ok, vamos lá! A primeira coisa a fazer é adicionar uma referência para o jquery na nossa view. O Jquery já vem por padrão na pasta Scripts das aplicações ASP.NET MVC. Arraste o arquivo para a view. Vamos então configurar nosso formulário para utilizar o Jquery submetendo as informações através de ajax:

 1 $(function () {
 2     config_add_products();
 3 });
 4 function config_add_products() {
 5     $("#novo_produto").submit(function (e) {
 6         e.preventDefault();
 7         $.ajax({
 8             url: $(this).attr("action"),
 9             data: $(this).serialize(),
10             success: function (retorno) {
11                 $("#products").append(retorno);
12         }});
13     });
14 }

O que fazemos é bem simples. Na linha 1 fazemos uma chamada para o Jquery configurar nosso formulário. Na linha 5 estamos definindo o evento de submit do nosso form. Na linha 6 cancelamos o submit padrão, ou seja, a página não será postada inteira para o servidor. Na linha 8 começa a mágica onde fazemos uma chamada para a função ajax do Jquery. Esta função recebe configurações através de chave-valor. A primeira informação que estamos enviando é a url e fazemos isso pegando o atributo action do nosso formulário na linha 9.Na linha 10 estamos informando os dados que devem ser enviados para o servidor, neste caso os dois campos do nosso formulário serializados em Json. Na linha 11 estamos informando uma função de callback, ou seja, uma função que será executada quando nossa requisição terminar com sucesso. E o que essa função faz é adicionar o resultado do servidor na nossa tabela de produtos. Sério, é tudo muito simples. E por que estamos adicionando o resultado do servidor direto no HTML? Veja você mesmo a alteração que fizemos no nosso controller:

1 public ActionResult AddProduct(Product newProduct){
2     var products = Session["products"] as List<product>;
3     products.Add(newProduct);
4 
5     if(Request.IsAjaxRequest())
6         return PartialView("RowSingleProduct", newProduct);
7 
8     return RedirectToAction("Index");
9 }

Repare na linha 5 adicionamos uma verificação para saber se a chamada para a action veio de um contexto ajax. Caso tenha sido uma chamada Ajax não redirecionamos para a action Index, ao invés disso retornamos uma partial view com o resultado do novo produto. Isso nos permite ter uma mesma action atuando com Ajax e sem Ajax.

A Partial View retornada e muito simples, responsável por renderizar uma única linha da tabela de produtos:

@model IEnumerable<aspnetmvc_jquery_ajax.controllers.product>
<tr>
    <td>@Model.Description</td>
    <td>@String.Format("{:F}", Model.Price)</td>
</tr>

Apenas cria uma <tr> com os dados do produto, e é essa tr que damos append na nossa table de produtos na Index.

Tratando os erros

É muito comum que só seja definida a callback para o sucesso da requisição, porém podem ocorrer erros e precisamos tratá-los de maneira adequada também.

Para isso vamos definir um callback de erro na função ajax do Jquery:

function config_add_products() {
    $("#novo_produto").submit(function (e) {
        e.preventDefault();
        $.ajax({
            url: $(this).attr("action"),
            data: $(this).serialize(),
            success: function (retorno) {
                $("#products").append(retorno);
            },
            error: function(erro){alert(erro);}
        });
    });
}

Desta forma daremos um alert informando o erro ocorrido. É preciso ficar atento ao tipo de erro senão o alert exibirá algo como "[object]" ou "[XmlHttpRequest]".

Exibindo sinalização de progresso

Podemos melhorar um pouco as coisas exibindo uma sinalização de que a requisição está sendo processada. Vamos criar uma div na nossa view contendo uma imagem de progesso:

<div id="progress" style="display: none;">
    <img src="progresso.gif" />
</div>

Feito isso vamos alterar nosso código javascript para que fique assim:

 1 function config_add_products() {
 2     $("#novo_produto").submit(function (e) {
 3         $("#progress").show();
 4         e.preventDefault();
 5 
 6         $.ajax({
 7             url: $(this).attr("action"),
 8             data: $(this).serialize(),
 9             success: function (retorno) {
10                 $("#products").append(retorno);
11             },
12             error: function(erro){alert(erro);},
13             complete: function () { $("#progress").hide();}
14         });
15     });
16 }

Reparem que na linha 3 estamos exibindo nossa imagem de progresso. E na linha 13 definimos mais uma função de callback para a função ajax do Jquery. Desta vez configuramos uma função para ser executada quando o request terminar, independente de erro ou sucesso, e o que fazemos é esconder a imagem de progresso. Desta forma sempre que a requisição ajax terminar a imagem é escondida.

Definindo requisição como GET ou POST

É importante ainda poder configurar o request para ser feito via GET ou POST. A ação de incluir um novo produto não deveria ser feita via GET, no entando GET é o type default para as requisições feitas com a função ajax do Jquery. Para alterarmos isso podemos utilizar a configuração type, veja abaixo:

 1 function config_add_products() {
 2     $("#novo_produto").submit(function (e) {
 3         $("#progress").show();
 4         e.preventDefault();
 5 
 6         $.ajax({
 7             url: $(this).attr("action"),
 8             type: POST,
 9             data: $(this).serialize(),
10             success: function (retorno) {
11                 $("#products").append(retorno);
12             },
13             error: function(erro){alert(erro);},
14             complete: function () { $("#progress").hide();}
15         });
16     });
17 }

Processando ajax com ASP NET MVC e Jquery

Ajax com ASP NET MVC e Jquery

Resumo

É muito simples trabalhar com Ajax usando Jquery no ASP.NET MVC. É preciso ter um pouco de conhecimento da API do Jquery, mas isto não é problema já que a própria documentação possui exemplos e descrições muito bem feitos.

O processo segue basicamente um mesmo script: Faça a página funcionar sem Ajax. Adicione o comportamento Ajax no cliente e no server.

Em um próximo post mostrarei alguns atalhos para trabalharmos com Ajax: $.get e $.post.

Baixe ou visualize o código fonte no github: https://github.com/vquaiato/ASP.NET-MVC-Jquery-Ajax

Abraços,

Vinicius Quaiato.

Voltar

Fork me on GitHub