Refrescar un WebGrid cada X tiempo de forma asíncrona

Con la nueva versión ASP.NET MVC 3, disponemos de una nueva extensión para la creación de grids. Para conocer más detalles sobre este nuevo helper podéis consultar el artículo de Jose M. Aguilar :)

En este post me gustaría mostraros cómo es posible actualizar de forma asíncrona un grid cada un número determinado de segundos.

Del lado del servidor he adjuntado una base de datos con una única tabla para el ejemplo que os quiero mostrar:

Un repositorio para recuperar los valores:


using System.Linq;

namespace WebGridAsync.Models
{
    public class StuffRepository
    {
        private readonly StuffEntities _model;
        public StuffRepository()
        {
            _model = new StuffEntities();
        }

        public FileViewModel GetFiles(int page = 1)
        {
            var fileViewModel = new FileViewModel();
            var files = _model.Files.ToList();
            fileViewModel.FilesPerPages = 5;
            fileViewModel.NumberOfFiles = _model.Files.Count();
            fileViewModel.Files = files.Skip((page - 1) * fileViewModel.FilesPerPages)
                                       .Take(fileViewModel.FilesPerPages);
            return fileViewModel;
        }

        public void SaveChanges()
        {
            _model.SaveChanges();
        }
    }
}

Y por último un controlador donde lo que vamos a actualizar es el estado de los archivos en cada llamada:

using System.Web.Mvc;
using WebGridAsync.Models;

namespace WebGridAsync.Controllers
{
    public class HomeController : Controller
    {
        private readonly StuffRepository _stuffRepository;
        public HomeController()
        {
            _stuffRepository = new StuffRepository();
        }

        public ActionResult Index(int page = 1)
        {
            return View(GetFilesWithUpdatedStatus());
        }

        public FileViewModel GetFilesWithUpdatedStatus()
        {
            var fileViewModel = _stuffRepository.GetFiles();

            foreach (var myFile in fileViewModel.Files)
            {
                switch (myFile.Status)
                {
                    case "Pending":
                        myFile.Status = "Processing";
                        break;
                    case "Processing":
                        myFile.Status = "Waiting";
                        break;
                    case "Waiting":
                        myFile.Status = "More waiting...";
                        break;
                    case "More waiting...":
                        myFile.Status = "Completed";
                        break;
                    default:
                        myFile.Status = "Pending";
                        break;
                }
            }

            _stuffRepository.SaveChanges();
            return fileViewModel;
        }
    }
}

Por último, necesitamos crear una vista donde hagamos uso del helper WebGrid. Es importante que el mismo esté incluido en un div con un id asociado.

@model WebGridAsync.Models.FileViewModel
@{
    ViewBag.Title = "Async WebGrid";

    WebGrid grid = new WebGrid(rowsPerPage: Model.FilesPerPages, canSort: false);
    grid.Bind(Model.Files, rowCount: Model.NumberOfFiles);
}
<h2>@ViewBag.Message</h2>
<div id="myWebGrid">
    @grid.GetHtml(columns: new[]{
    grid.Column("Name"),
    grid.Column("Date"),
    grid.Column("Status")
})
</div>

Para hacer la llamada asíncrona, necesitamos utilizar algo de código javascript, con la ayuda de JQuery. En la misma página que el grid anterior incluimos lo siguiente:

<script language="javascript" type="text/javascript">

    $(document).ready(function () {
        $.ajaxSetup({
            cache: false
        });

        setTimeout(reloadAsync, 5000);
    });

    function reloadAsync() {
        $("#myWebGrid").load("/Home/Index #myWebGrid", function (response, status, xhr) {
            if (status == "error") {
                var msg = "Sorry but there was an error: ";
                $("#error").html(msg + xhr.status + " " + xhr.statusText);
            }
            else {
                setTimeout(reloadAsync, 5000);
            }

        });

    }
</script>

Lo que estamos haciendo en realidad es inicializar un timer para que cada 5 segundos solicite los datos al servidor. El método load de JQuery va a realizar una llamada a la acción Index del controlador Home para que este le devuelva la página renderizada. Una vez obtiene el resultado va a localizar el elemento div myWebGrid para reemplazar el que se está visualizando actualmente por el nuevo resultado.

Adjunto el proyecto por si fuera de utilidad :D

¡Saludos!

2 comentarios sobre “Refrescar un WebGrid cada X tiempo de forma asíncrona

  1. Y lo cómodo que era simplemente tirar un Timer dentro de un UpdatePanel. ;) Evidentemente despues toda esa “mágia” la pagabas cara, pero…

Deja un comentario